在C中,当我移动这个printf行时: printf("%fn", 5 / 2);
它的输出变化到不同的行。 有任何想法吗?
inheritance人代码:
#include #include int main() { int a = 65; char c = (char)a; int m = 3.0/2; printf("%cn", c); printf("%fn", (float)a); printf("%fn", 5.0 / 2); printf("%fn", 5 / 2.0); printf("%fn", (float)5 / 2); printf("%fn", 5 / (float)2); printf("%fn", (float)(5 / 2)); printf("%fn", 5.0 / 2); printf("%dn", m); printf("%fn", 5 / 2); system("PAUSE"); return(0); }
继续输出:
A 65.000000 2.500000 2.500000 2.500000 2.500000 2.000000 2.500000 1 2.500000
如果我移动printf("%fn", 5 / 2);
到第一行之一(在输出A的那一行和输出65.000000的那一行之间)它将打印0.000000(这是有意义的)而不是现在的25000000。 有任何想法吗?
您的代码正在调用未定义的行为。
您有义务使用正确的数据说明符在printf
打印内容,如果不这样做则调用UB。 因此,在不同的地方获得不同的结果并不重要也就不足为奇了。
如果转换规范无效,则行为未定义。
c也是如此。
在调用未定义的行为时,结果是按照定义随机且不可预测的,因此要求我们预测它们毫无意义。
正如评论者指出的那样,行printf("%fn", 5 / 2);
只是表现出未定义的行为。 但是,让我们看看为什么你可以使用System V ABI在x86-64架构上获得这样的结果。
简短的回答是前几个参数是通过寄存器传达的。 选择取决于参数的类型:整数参数进入“经典”寄存器( edi
, esi
等),浮点进入SSE寄存器( xmm0
, xmm1
等)。
因为我们在格式字符串中给出了错误的类型,所以printf
正在从错误的寄存器中读取参数。
让我们将您的程序简化为以下内容:
#include int main(void) { printf("%fn", 5/2); printf("%fn", 5.0/2); printf("%fn", 5/2); return 0; }
现在让我们来看看main
的反汇编。 我们从function序言开始,这不是太特别:
push %rbp mov %rsp,%rbp sub $0x10,%rsp
然后,我们第一次调用printf
,其中参数传递给edi
(获取指向格式字符串的指针)和esi
( 5/2
,由于整数除法为2
):
mov $0x2,%esi mov $0x4005e4,%edi mov $0x0,%eax callq 4003e0
但是, printf
将读取"%fn"
格式并尝试从xmm0
读取参数。 在我的例子中,该寄存器的值为0
,因此打印出0.000000
。
在第二个调用中,参数显然是一个浮点数,它通过xmm0
传递:
movabs $0x4004000000000000,%rax mov %rax,-0x8(%rbp) movsd -0x8(%rbp),%xmm0 mov $0x4005e4,%edi mov $0x1,%eax callq 4003e0
现在, printf
打印出预期的2.500000
(你在这里看到的是0x4004000000000000
,这就是2.5的64位浮点常量)。 我们将它传递给xmm0
,它从xmm0
读取它。
第三个电话与第一个电话完全相同:
mov $0x2,%esi mov $0x4005e4,%edi mov $0x0,%eax callq 4003e0
更改的是对printf
的调用没有改变xmm0
的值。 它仍然包含第二次调用之前的常量2.5,因为我们第三次调用printf
。 在第三次调用中, printf
将再次打印2.500000
。
(我们的function以无聊的return 0
结束,当然:)
mov $0x0,%eax leaveq retq
以上就是c/c++开发分享将printf移动到不同的行会产生不同的输出? (C)相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/545047.html