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
打印float
和double
和%ld
打印很长时间
C99清楚地说(wrt printf
和fprintf
)
如果转换规范无效,则行为未定义。 如果任何参数不是相应转换规范的正确类型,则行为未定义。