int a=5;
float b=3.5;
printf("%d",b);
printf("\n%f",a);
任何人都可以告诉我为什么这段代码显示意外的输出(垃圾\ n3.5)
答案 0 :(得分:4)
根据您对a
和b
的声明,格式化字符串不正确错误:
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);
问: - 为什么要获得该输出?
这是由于代码的未定义行为:
来自INTERNATIONAL STANDARD ©ISO/IEC ISO/IEC 9899:201x
7.16.1变量参数列表访问宏
(第270页)
7.16.1.1
va_arg
宏[...]如果没有实际的下一个参数,或者类型不兼容 实际下一个参数的类型(根据 默认参数促销),
behavior is undefined
,除以下情况外:
- 一种类型是signed integer type
,另一种类型是 对应的unsigned integer
类型,值可表示 两种类型;
- 一种是指向void
的指针,另一种是指针 指向字符类型的指针
答案 1 :(得分:3)
您正在为float
格式字符串传递%d
,但printf
期待int
。
printf
是一个变量参数列表函数:printf(const char *format_string,...);
这意味着格式字符串之后的其余参数可以是任何类型和数字,并且编译器不知道它们应该是什么。程序员可以提供printf
所期望的类型的参数。 printf
期望的内容由格式字符串决定。当您在格式字符串中给出%d
时,printf函数将期望下一个参数是int
。由于你传递的是float
,可能会发生一些奇怪的事情。例如,组成浮点数的那些字节可能被视为int
,它们不会给你任何有意义的值。
实际上它比这复杂一点。有关如何将参数传递给变量参数函数的特殊规则。其中一条规则是float
值作为double
传递。这意味着您的float
值在传递给double
之前首先转换为printf
。最有可能的是double
是您平台上的八个字节,而int
只有四个字节。因此,printf
函数可以将double
值的前四个字节视为int
。
更糟糕的是,在下一行,int
正在传递double
。这意味着printf
函数可以将int
的前四个字节视为double
的一部分,然后读取另外四个甚至不属于您的参数的字节。< / p>
实际发生的细节是特定于平台的。该语言只是声明你不应该传递错误类型的参数,并且如果你这样做就不会保证会发生。
答案 2 :(得分:1)
因为a
变量是int类型,而您为float类型指定了格式字符串,反之亦然为变量b
。
注意:
%d
适用于整数类型
%f
适用于 float 类型
您应该使用:
int a=5;
float b=3.5;
printf("%f",b);
printf("\n%d",a);
答案 3 :(得分:1)
int main()
{
int a=5;
float b=3.5;
printf("%f",b); //Use %f
printf("\n%d",a); // Use %d
}
参考:printf
printf
的错误格式说明符导致大多数情况下未定义的行为。
但是,因为printf
是一个可变函数,并且是variadic的参数
函数经过默认参数cast。
比如,char被转换为int。