【问题标题】:Why are the int and float passed in printf going to the wrong positions in the format string?为什么在 printf 中传递的 int 和 float 会转到格式字符串中的错误位置?
【发布时间】:2017-11-18 03:56:40
【问题描述】:

printf function int to %f , float to %d 尝试实验

#include<stdio.h>                                              
int main(){                                                    
    int i=10;                                                     
    float x=43.2892f;                                              
    printf("i=%f  x=%d \n",i,x);                               
    return 0;                                                  
}

输出:

i=43.289200  x=10      

需要帮助了解为什么这些变量会互换?

【问题讨论】:

  • 欢迎来到未定义行为领域。人口:INT_MAX + 1.
  • 您可以随心所欲地进行实验,但是您想出的结果完全没有用,因为您看到的是未定义的行为
  • 嗯,它是 UB,但是查看 generated assembly 很明显,浮点数是在浮点寄存器中传递的,而整数是在常规寄存器中传递的,printf 可能会寻找这些寄存器中的变量。
  • @narutowindy 未定义的行为可以做任何事情。它不必是随机的,它可以是一致的。
  • @narutowindy 每次都会产生不同的结果 - 听起来你是在定义行为?

标签: c printf format-specifiers


【解决方案1】:

你正在做的事情会调用未定义的行为1,但是在System V AMD64 ABI 的平台上使用 GCC 来查看the resulting assembly,我们可能会提出一个假设。浮点值在xmm0 寄存器(SSE 寄存器)中传递,而整数在esi 寄存器(通用寄存器)中传递。据推测,您的 printf 实现希望浮点数在 SSE 寄存器中传递,整数在通用寄存器中传递,并且在遇到第一个 %f 时简单地选择要读取的 xmm0 寄存器(反之亦然)。


1未定义的行为不必是“随机的”或“每次都不同”。在这种情况下,未定义的行为非常一致。未定义的行为甚至可能正是您所期望的;但是当你升级你的编译器时它也可能会改变。

【讨论】:

  • 这假设一个 x86-64 架构,以及一些 ABI
  • 我们是如何到达那里的?也许在实现的深处,有些东西会查看传入的内容和请求的内容,然后得出结论:“嗯。程序员搞砸了。我来解决。”
  • @BasileStarynkevitch:将这个假设添加到文本中。
  • @user4581301:这只是 ABI 的一部分。如果你传递一个 float 和一个 int,它们会进入 xmm0 和 eax。如果你通过一个 int 和一个 float,它们会进入 eax 和 xmm0。
  • @You 哪个平台有这样一个奇怪的 ABI,它通过 xmm0 中的第三个参数但 printf 实现可以从 xmm0 中选择第二个参数?
猜你喜欢
  • 1970-01-01
  • 2020-11-10
  • 1970-01-01
  • 2012-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-30
相关资源
最近更新 更多