我写了这个小代码:
#include <stdio.h>
int main() {
size_t temp;
temp = 100;
printf("lld=%lld, ld=%ld, u=%u\n", temp, temp, temp);
return 0;
}
我在装有 gcc 4.1.1 20070105 (Red Hat 4.1.1-52) 的 i386 GNU/Linux 机器上运行。这是我得到的输出:
lld=429496729700, ld=100, u=7993461
我可以理解第一个 (lld
) 被打印为垃圾,因为 printf
试图打印 8 个字节(对于 signed long long
如 lld
所示)当变量 temp
中只有 4 个字节可用时。
但是,我不明白为什么最后一个标识符 u
被打印为垃圾 - 而据我所知,这是最接近 size_t
的适用标识符。
这里我假设 size_t
是 unsigned int
(对于我的 i386,它是有符号的 4 字节)。
现在,我对 printf
行做了一些调整:
...
printf("ld=%ld, u=%u, lld=%lld\n", temp, temp, temp);
...
我有一个完美的答案(lld
部分除外)。
ld=100, u=100, lld=34331653576851556
有人可以帮我理解我到底错过了什么吗?
非常感谢您的帮助!
[旁注:我尝试使用 gcc -O[0,2]
标签打开/关闭优化,观察结果没有任何差异。]
最佳答案
那是因为您压入堆栈的是三个 32 位值,而您的格式字符串试图使用其中的四个,或者更准确地说,一个 64 位值和两个 32 位值。
在第一种情况下,lld
获取两个 32 位值,ld
获取第三个值,u
获取之后发生在堆栈中的任何东西,实际上可以是任何东西。
当您更改字符串中格式说明符的顺序时,它的工作方式不同,因为 ld
吸收了第一个 32 位值,u
吸收了second 和 lld
吸取第三个 plus 之后堆栈中的任何内容。这就是您获得不同值的原因,这是一个数据对齐/可用性问题。
您可以看到第一个值的实际效果。 429496729700 等于 (4294967296 + 1) * 100
,即 (232+1)*100。你的代码片段
printf("lld=%lld, ld=%ld, u=%u\n", temp, temp, temp);
实际有以下作用:
What you pass Stack What printf() uses
------------- ----- ------------------
+-----+
100 | 100 | \
+-----+ = 64-bit value for %lld.
100 | 100 | /
+-----+
100 | 100 | 32-bit value for %ld.
+-----+
| ? | 32-bit value for %u (could be anything).
+-----+
第二种情况
printf("ld=%ld, u=%u, lld=%lld\n", temp, temp, temp);
发生以下情况:
What you pass Stack What printf() uses
------------- ----- ------------------
+-----+
100 | 100 | 32-bit value for %ld.
+-----+
100 | 100 | 32-bit value for %u.
+-----+
100 | 100 | \
+-----+ = 64-bit value for %lld (could be anything).
| ? | /
+-----+
关于c - 带有 lld、ld 和 d 类型标识符的 size_t 变量的 printf,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2424528/