我写了这个小代码:
#include <stdio.h>
int main() {
size_t temp;
temp = 100;
printf("lld=%lld, ld=%ld, u=%u\n", temp, temp, temp);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我在带有gcc版本4.1.1 20070105(Red Hat 4.1.1-52)的i386 GNU/Linux机器上运行它.这是我得到的输出:
lld=429496729700, ld=100, u=7993461
Run Code Online (Sandbox Code Playgroud)
我可以理解第一个(lld
)被打印为垃圾,因为当变量中只有4个字节可用时,printf
尝试打印8个字节(用于signed long long
表示lld
)temp
.但是,我无法理解为什么最后一个标识符u
被打印为垃圾 - 而在我的理解中,这是最接近的适用标识符size_t
.
这里我假设size_t
是unsigned int
(我的i386签名为4个字节).
现在,我对该printf
线进行了一些调整:
...
printf("ld=%ld, u=%u, lld=%lld\n", temp, temp, temp);
...
Run Code Online (Sandbox Code Playgroud)
我有一个非常好的答案(lld
部分除外).
ld=100, u=100, lld=34331653576851556
Run Code Online (Sandbox Code Playgroud)
有人可以帮我理解我在这里错过了什么吗?
非常感谢您的帮助!
[旁注:我尝试使用gcc -O[0,2]
标签开/关切换优化,但观察结果没有任何差异.]
pax*_*blo 23
那是因为你在堆栈上推送的是三个32位值,你的格式字符串试图使用其中的四个,或者更确切地说,一个64位值和两个32位值.
在第一种情况下,lld
吸收了两个32位值,ld
吸收了第三个值,然后u
得到堆栈中发生的任何事情,这可能真的是什么.
当你改变字符串中格式说明符的顺序时,它的工作方式不同,因为它ld
吸收了第一个32位值,u
吸收了第二个,lld
吸收了第三个加上之后发生在堆栈上的任何事情.这就是为什么你得到不同的价值,这是一个数据对齐/可用性问题.
您可以使用第一个值查看此操作.429496729700等于(4294967296 + 1) * 100
,即(2 32 +1)*100.你的代码片段
printf("lld=%lld, ld=%ld, u=%u\n", temp, temp, temp);
Run Code Online (Sandbox Code Playgroud)
实际上有以下效果:
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).
+-----+
Run Code Online (Sandbox Code Playgroud)
在第二种情况下
printf("ld=%ld, u=%u, lld=%lld\n", temp, temp, temp);
Run Code Online (Sandbox Code Playgroud)
发生以下情况:
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).
| ? | /
+-----+
Run Code Online (Sandbox Code Playgroud)
您的代码恰当地演示了未定义的行为.请注意,在可变参数的情况下,不会对参数进行类型检查.这是一个必要的明确演员.实际上应该使用以下内容:
printf("lld=%lld, ld=%ld, u=%u\n",
(unsigned long long)temp,
(unsigned long)temp,
(unsigned int)temp);
Run Code Online (Sandbox Code Playgroud)
顺便一下,请记住size_t
is 的说明符z
.所以:
printf("zd=%zd\n", temp);
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
20400 次 |
最近记录: |