C程序中出现意外结果

你能解释一下这个C程序的输出吗? 我想问题是在printf("%d\n",t);期间堆栈printf("%d\n",t); 函数调用,因为我正在推动一个float但是读取一个int 。 我不确定。

 #include  int main() { long x; float t; scanf("%f",&t); printf("%d\n",t); x=30; printf("%f\n",x); { x=9; printf("%f\n",x); { x=10; printf("%f\n",x); } printf("%f\n",x); } x==9; printf("%f\n",x); } 

和输出

 $ ./a.out 20.39 0 20.389999 20.389999 20.389999 20.389999 20.389999 $ 

会发生什么事情是你撒谎到编译器…首先你告诉它你将发送一个int到printf,但你发送一个浮动代替,然后你告诉它你将发送一个double但你发送一个long而不是。

不要那样做。 不要欺骗编译器。

您已调用未定义的行为 。 任何事情都可能发生。 你的程序可能会破坏堆栈; 它可能会输出你所期望的; 它可能会使柠檬汁从USB端口流出; 它可能会让恶魔飞出你的鼻子 ; …

您使用错误的格式说明符来打印长。 请改用格式说明符%ld 。 结果

 printf("%f\n",x); // ^ change this to %ld 

实际发生的是:

  • 你的float是4个字节,你的long是4个字节,你的double是8个字节。
  • 你通过省略号传递一个float – 它被转换为一个double float 。 堆栈上有8个字节。
  • 你传递了一个long省略号 – 堆栈上的4个字节。
  • printf将堆栈上的8个字节( float说明符)解析为double 。 这个double将包含堆叠旧double的“重要”部分,以及最不重要部分( long )的轻微变化。
  • 默认%f输出截断值,您没有看到变化。

将所有%f更改为例如%.20f以查看long如何影响double

printf("%d\n",t);

在printf中使用不正确的格式说明符会调用未定义的行为。

使用%f打印floatdouble%ld打印很长时间

C99清楚地说(wrt printffprintf

如果转换规范无效,则行为未定义。 如果任何参数不是相应转换规范的正确类型,则行为未定义。