C程序中的意外结果
你能解释一下这个C程序的输出吗?我猜问题在于堆栈在C程序中的意外结果,c,C,你能解释一下这个C程序的输出吗?我猜问题在于堆栈在printf(“%d\n”,t)期间损坏函数调用,因为我正在按浮点,但正在读取int。我不确定 #include <stdio.h> int main() { long x; float t; scanf("%f",&t); printf("%d\n",t); x=30; printf("%f\n",x); { x=9;
printf(“%d\n”,t)期间损坏代码>函数调用,因为我正在按浮点
,但正在读取int
。我不确定
#include <stdio.h>
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);
}
您使用了错误的格式说明符来打印长字符。改用格式说明符%ld
。
结果是你对编译器撒谎。。。首先,您告诉它您将发送一个int
到printf,但您将发送一个float,然后您告诉它您将发送一个double
,但您将发送一个long
不要那样做。不要对编译器撒谎
您调用了未定义的行为。任何事情都有可能发生。您的程序可能会损坏堆栈;它可能输出您所期望的内容;它可能会使柠檬汁从USB端口流出;它可能会 printf(“%d\n”,t)代码>
在printf中使用不正确的格式说明符会调用未定义的行为
使用%f
打印float
和double
和%ld
打印长字符
C99清楚地表示(wrtprintf
和fprinf
)
如果转换规范无效,则行为未定义。如果有任何论点是正确的
对应转换规范的类型不正确,行为为
未定义
实际情况是:
- 你的
float
是4个字节,你的long
是4个字节,你的double
是8个字节
- 通过省略号传递一个
浮点值
——它将转换为双精度
。堆栈上有8个字节
- 在堆栈上通过省略号-4字节传递一个
long
李>
printf
将堆栈上的8个字节(float
说明符)解析为double
。此double
将包括堆栈上旧double
的“重要”部分,以及最不重要部分(您的long
)的细微变化李>
- 默认值
%f
输出截断该值,您看不到变化
将所有%f
更改为例如%.20f
,以查看长的如何影响双您需要在启用更多编译器警告的情况下编译代码,并注意它给您的警告(在将代码发布到之前)。@Jonathan Leffler:当我阅读Q时,他知道自己做错了,但想知道到底发生了什么。但他应该更明确,并包含编译器/平台信息。在AMD64上,前八个float
参数通过SSE寄存器传递,因此long
甚至不会覆盖其中的一部分。@aaz:行为匹配x86,所以我做了一件坏事,并假设:)-它匹配AMD64,所以我也假设:)但是%.20f
的结果会有所不同。@aaz:寄存器是否用于amd64/gcc上的省略号?每天学习新的东西:是的。省略号的唯一区别是,AL包含用于参数的SSE寄存器数量的上限。我知道这是错误的,我要求对输出进行解释。无论如何,谢谢。使用错误的格式说明符可能导致@Prasony引用标准中的任何内容。结果就是这样。
$ ./a.out
20.39
0
20.389999
20.389999
20.389999
20.389999
20.389999
$
printf("%f\n",x);
// ^ change this to %ld