c语言printf %llo,c++ - Printf疯狂了 - 堆栈内存溢出
你不能使用%d來打印long long 。 你必須使用%lld 。 (因此請使用"\\n%d %d | %lld %lld | %d %d"作為格式字符串。)
特別是,顯而易見的是,在“52 0 | 52 0”中,第一個52 0是a.rez ,第二個52 0是b.rez (這些中的每一個都是long long ,顯然是(從輸出)將兩個單詞推入堆棧)。 a.tonum不打印a.tonum和b.tonum 。
要理解為什么會發生這種情況,讓我解釋一下喬納森和我想說的話。 當你調用像一個可變參數函數printf (被聲明為類似printf(const char *format, ...)編譯器沒有辦法來驗證正確的參數類型的...在編譯時。因此,有在這種情況下決定在堆棧上推送什么的過程,大致可以概括為:如果它是int或可升級到int ,它將被推送為int ;如果它是double或可升級為double ,則它被推送為double ;否則,按原樣推送。
在實現像printf這樣的可變函數時,您需要一些方法來訪問...項目。 這樣做的方法是使用在聲明的va_list 。 這是一些偽代碼,顯示它是如何使用的:
int printf(const char *format, ...)
{
va_list ap;
va_start(ap, format);
while (/* we find the next format marker */) {
if (/* %d, %i, %c */) {
int val = va_arg(ap, int);
/* print out val as decimal or (for %c) char */
} else if (/* %u, %x, %X, %o */) {
unsigned int val = va_arg(ap, unsigned int);
/* print out val as decimal, hex, or octal */
} else if (/* %ld, %li */) {
long val = va_arg(ap, long);
/* print out val as decimal */
} else if (/* %lu, %lx, %lX, %lo */) {
unsigned long val = va_arg(ap, unsigned long);
/* print out val as decimal, hex, or octal */
} else if (/* %lld, %lli */) {
long long val = va_arg(ap, long long);
/* print out val as decimal */
} else if (/* %llu, %llx, %llX, %llo */) {
unsigned long long val = va_arg(ap, unsigned long long);
/* print out val as decimal, hex, or octal */
} else if (/* %s */) {
const char *val = va_arg(ap, const char *);
/* print out val as null-terminated string */
} /* other types */
}
va_end(ap);
return /* ... */;
}
請注意,每次要選擇...參數時,都要使用va_arg ,并且必須指定要選擇的類型。 您可以選擇正確的類型。 如果類型不正確,則會出現類型錯誤,在大多數情況下會出現未定義的行為(意味著程序可以執行任何喜歡的操作,包括崩潰或更糟)。
在您的特定計算機中,似乎當您通過long long ,它將64位數量推送到堆棧,但因為您使用了%d格式說明符,它使用了va_arg(ap, int)版本,它只抓取一個32位的數量。 這意味著64位字的另一半仍然未讀,后續%d然后繼續讀取。 這就是為什么在格式字符串完成時,它永遠不會處理你傳遞的a.tonum和b.tonum的值。
如果您正確使用%lld ,它將使用va_arg(ap, long long) ,并且可以正確讀取整個64位數量。
總結
以上是生活随笔為你收集整理的c语言printf %llo,c++ - Printf疯狂了 - 堆栈内存溢出的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 计算机路表配置命令,计算机、华为交换机、
- 下一篇: zabbix中mysql连不上的排错_z