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