printf的意外输出

int a=5; float b=3.5; printf("%d",b); printf("\n%f",a); 

任何人都可以告诉我为什么这段代码显示意外的输出(垃圾\ n3.5)

格式字符串不正确错误,根据您对ab声明:

 printf("%d",b); <-- "b is float" Wrong! printf("\n%f",a); <-- "a is an int" Wrong! -- Undefined behavior 

应该:

 printf("%f",b); printf("\n%d",a); 

问: -为什么你得到那个输出?

这是由于代码的未定义行为:

来自国际标准©ISO / IEC ISO / IEC 9899:201x

7.16.1变量参数列表访问宏

(第270页)

7.16.1.1 va_arg

[...]如果没有实际的下一个参数,或者type与实际的下一个参数的类型不兼容(根据默认参数提升而提升),则behavior is undefined ,除了以下情况:
- 一种类型是有signed integer type ,另一种类型是相应的unsigned integer类型,并且该值可在两种类型中表示;
- 一种是指向void的指针,另一种是指向字符类型的指针

您正在为%d格式字符串传递一个float ,但printf期望一个int

printf是一个变量参数列表函数: printf(const char *format_string,...);

这意味着格式字符串之后的其余参数可以是任何类型和数字,并且编译器不知道它们应该是什么。 程序员可以提供printf所期望的类型的参数。 printf期望的内容由格式字符串决定。 当你在格式字符串中给出%d时,printf函数将期望下一个参数是int 。 因为你正在传递一个float ,所以可能会发生一些奇怪的事情。 例如,构成浮点数的那些字节可能被视为int ,这不会给你任何有意义的值。

实际上它比那复杂一点。 有关如何将参数传递给变量参数函数的特殊规则。 其中一条规则是float值传递为double s。 这意味着您的float值在传递给printf之前首先转换为double 。 很可能你的平台上有一个double是8个字节,而int只有4个。 因此printf函数可以将double值的前四个字节视为int

更糟糕的是,在下一行中,正在传递一个int ,其中double是预期的。 这意味着printf函数可以将int的前四个字节视为double一部分,然后读取另外四个甚至不是参数的字节。

实际发生的细节是特定于平台的。 语言只是声明你不应该传递错误类型的参数,如果你这样做,就不会保证会发生。

因为a变量是int类型,而你是为float类型指定格式字符串,反之亦然为变量b

注意 :

%d用于整数类型

%f浮点

你应该使用:

 int a=5; float b=3.5; printf("%f",b); printf("\n%d",a); 
 int main() { int a=5; float b=3.5; printf("%f",b); //Use %f printf("\n%d",a); // Use %d } 

参考: printf

printf格式说明符错误导致大多数情况下未定义的行为。

但是,由于printf是一个可变函数,并且可变参数函数的参数经过默认参数cast。 就像,char被转换为int。