试试285212672ULL;如果你写它没有后缀,你会发现编译器把它当作一个常规整数。它在变量中工作的原因是整数在赋值中被转换为unsigned long long,因此传递给printf() 的值是正确的类型。
在你问之前,不,编译器可能不够智能从printf() 格式字符串中的"%llu" 中找出它。这是不同的抽象级别。编译器负责语言语法,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 位 ULL 值,2 x 232 + 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).
+------------+