c/c++语言开发共享将printf移动到不同的行会产生不同的输出? (C)

在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架构上获得这样的结果。

    简短的回答是前几个参数是通过寄存器传达的。 选择取决于参数的类型:整数参数进入“经典”寄存器( ediesi等),浮点进入SSE寄存器( xmm0xmm1等)。

    因为我们在格式字符串中给出了错误的类型,所以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 (获取指向格式字符串的指针)和esi5/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

      (0)
      上一篇 2021年1月10日
      下一篇 2021年1月10日

      精彩推荐