printf - 奇怪的混杂结果。有人可以解释一下吗?

Posted

技术标签:

【中文标题】printf - 奇怪的混杂结果。有人可以解释一下吗?【英文标题】:printf - Weird type mishmash result. Can someone explain this? 【发布时间】:2015-09-04 19:46:20 【问题描述】:

在处理一个从二进制文件读取结构数据类型的简单项目时,我遇到了一个奇怪的 printf 格式类型混杂。基本上,我大部分时间都使用%u 格式来显示无符号整数,而在我的结构中是一个类型为unsigned long long 的成员,使用格式字符显示此数据会导致一些奇怪,并且会浪费几个小时来搜索打错了。

这是一个例子:

struct bar 
    unsigned long long ll;
    unsigned int i1;
    unsigned int i2;
;

int main(void)

    bar fubar;
    fubar.ll = 1200;
    fubar.i1 = 2500;
    fubar.i2 = 450;

    printf("Debt: %u Euro, Wallet: %u Euro, Outgoings: %u Euro.\n", fubar.ll, fubar.i1, fubar.i2);

    return 0;

结果:

债务:1200 欧元,钱包:0 欧元,支出:2500 欧元。

使用 Visual Studio 2013 编译。

当然,当我使用%llu 格式时,一切都按预期工作。

这是因为printf 的工作方式和实现方式造成的吗?

【问题讨论】:

Cannot repro。你用的是什么编译器? 未定义的行为是未定义的。 相关:***.com/q/1748856/694576 【参考方案1】:

unsigned long long 将与%llu 一起打印。使用不匹配类型的变量会调用未定义的行为。

引用C11,第 7.21.6.1 章

ll (ell-ell)

指定后面的 d、i、o、u、x 或 X 转换说明符适用于 long long int 或 unsigned long long int 参数;

关于 UB,

[..] 如果有任何参数 不是相应转换规范的正确类型,行为是 未定义。

【讨论】:

【参考方案2】:

我无法使用我的编译器在我的计算机上复制此行为。但是,报告的行为在 ideone 被复制:https://ideone.com/mCihqW。

问题在于您正在调用未定义的行为。对printf 的调用中的第二个参数是一个无符号长整型,但第一个格式指令是%u。那是不匹配。您应该使用 %llu 作为格式指令。 printf 的格式指令必须与参数匹配。如果没有,该函数会表现出未定义的行为。

不知道对未定义行为的响应会是什么。

我怀疑您的计算机上发生的事情,以及您的编译器(可能也在 ideone.com 上)是调用堆栈填充了

指向格式指令的指针(四个或八个字节), 值为 1200(8 个字节)的无符号 long long, 一个值为 2500(四个字节)的无符号整数,并且 值为 450(另外四个字节)的无符号整数。

在看到格式指令中的第一个%u 时,printf 会检查调用堆栈中格式指令之后的四个字节(不是八个)。您可能正在一台小端计算机上运行。被解释为无符号整数的前四个字节包含 1200,所以这就是打印的内容。

看到下一个%uprintf 会检查调用堆栈中接下来的四个字节。这四个字节是您的调用推入调用堆栈的 unsigned long long 的高位一半。由于 1200 比 232 小很多,所以 unsigned long long 的上半部分全为零。所以printf 在你的钱包里打印出 0 欧元。

看到最后一个%uprintf 再次检查调用堆栈,这次从格式指令结束后的八个字节开始。接下来的四个字节,作为一个无符号整数,包含 2500。这就是 printf 输出的输出。

如上所述,我没有在我的计算机上看到这种行为。我看到了另一种形式的未定义行为。不要试图理解未定义的行为。除非您真的知道自己在做什么并且愿意承受后果(例如,不可移植性、鼻恶魔、硬盘擦除),否则不要调用未定义的行为。

【讨论】:

以上是关于printf - 奇怪的混杂结果。有人可以解释一下吗?的主要内容,如果未能解决你的问题,请参考以下文章

有人可以解释为啥条件运算符和赋值运算符一起使用时表现奇怪吗?

有人可以解释一下这个程序的输出是怎样的吗

QFontMetrics 给出等宽字体的奇怪结果

有人可以解释 UIView 的奇怪旋转吗?

有人可以解释一下这个例子中 CSS 中的“溢出”到底对背景做了啥吗? [复制]

解释一下,下面一段程序,每句代码的含义,以及输出结果。