采取以下措施:
#include <stdio.h> main() { unsigned long long verybig = 285212672; printf("Without variable : %llu\n",285212672); printf("With variable : %llu",verybig); }
这是上面程序的输出:
Without variable : 18035667472744448 With variable : 285212672
从上面可以看出,当printf通过数字作为常量时,它会打印出一些非常大的不正确的数字,但是当该值首先存储在变量中时,printf会输出正确的数字.
这背后的原因是什么?
解决方法
尝试285212672ULL;如果你没有后缀,你会发现编译器把它当成一个正则整数.它在变量中工作的原因是因为整数在赋值中被转换为无符号long long,因此传递给printf()的值是正确的类型.
在你问之前,不,编译器可能不够聪明,不能从printf()格式字符串中的“%llu”中找出它.这是一个不同的抽象层次.编译器负责语言语法,printf()语义不是语法的一部分,它是一个运行时库函数(与标准中包含的函数不同).
考虑以下32位int和64位无符号long long系统的代码:
#include <stdio.h> int main (void) { printf ("%llu\n",1,2); printf ("%llu\n",1ULL,2); return 0; }
其输出:
8589934593 1
在第一种情况下,两个32位整数1和2被推送到堆栈,printf()将其解释为单个64位ULL值2 x 232 1.两个参数无意中包含在ULL值中.
在第二个,你实际上推64位1值和一个多余的32位整数2,这被忽略.
请注意,您的格式字符串与实际参数之间的“脱离步骤”是一个坏主意.就像是:
printf ("%llu %s %d\n","hello",0);
可能会崩溃,因为32位“hello”指针将被%llu消耗,%s将尝试取消引用最终的0参数.以下“图片”说明了这一点(我们假设单元格是32位,“hello”字符串存储在0xbf000000.
What you pass Stack frames What printf() uses +------------+ 0 | 0 | \ +------------+ > 64-bit value for %llu. "hello" | 0xbf000000 | / +------------+ 0 | 0 | value for %s (likely core dump here). +------------+ | ? | value for %d (could be anything). +------------+