尝试使用285212672ULL
;如果你不加后缀写它,编译器会将它视为普通整数。在变量中它可行是因为在赋值时将整数强制转换为unsigned long long
,这样传递给printf()
的值就是正确的类型。
在你问之前,不,编译器可能不能从"%llu
"的printf()
格式字符串中推断出来。那是一个不同层面的抽象。编译器负责语言语法,printf()
语义不是语法的一部分,它是运行时库函数(与你自己的函数没有什么区别,只是它被包含在标准库中)。
考虑以下32位int和64位unsigned 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位的无符号长整型值,即2 x 2
32 + 1。无意中将
2
参数包括在ULL值中。
在第二种情况下,实际上您推送了64位的1值和一个多余的32位整数
2
,该值将被忽略。
请注意,格式字符串和实际参数之间的"失步"是不好的做法。例如:
printf ("%llu %s %d\n", 0, "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).
+------------+