我写了这个小代码:
#include <stdio.h>
int main() {
size_t temp;
temp = 100;
printf("lld=%lld,ld=%ld,u=%u\n",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)被打印为垃圾,因为当可变temp只有4个字节时,printf尝试打印8个字节(由lld表示的long long).
但是,我不明白为什么最后一个标识符u被打印为垃圾,而在我看来,这是size_t最接近的适用标识符.
这里我假设size_t是unsigned int(我的i386有4个字节).
现在我用printf线做了一点调整:
...
printf("ld=%ld,u=%u,lld=%lld\n",temp);
...
我有一个非常好的答案(除了lld部分).
ld=100,u=100,lld=34331653576851556
有人可以帮我理解我在这里错过什么吗?
非常感谢任何帮助!
[注意:我尝试使用gcc -O [0,2]标签打开/关闭切换优化,观察结果没有任何差异.]
解决方法
这是因为您在堆栈中推送的是三个32位值,格式字符串尝试使用其中的四个值,或者更精确地使用一个64位值和两个32位值.
在第一种情况下,lld吸收了两个32位值,ld吸收了第三个值,并且在这之后,你会发现任何事情发生在堆栈上,这真的是任何事情.
当您更改字符串中格式说明符的顺序时,它的作用不同,因为ld吸收了第一个32位值,您吸收了第二个,而lld吸收了第三个加上任何恰好在堆栈上的事情.那.这就是为什么你得到不同的值,这是一个数据对齐/可用性问题.
您可以使用第一个值查看此操作. 429496729700等于(4294967296 1)* 100,即(232 1)* 100.你的代码段
printf("lld=%lld,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,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).
| ? | /
+-----+