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;

你能解释一下这个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("%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清楚地表示(wrt
printf
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