printf的意外输出

时间:2013-07-27 13:11:52

标签: c casting printf garbage

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

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

4 个答案:

答案 0 :(得分:4)

根据您对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);
  

问: - 为什么要获得该输出?

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

来自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。

相关问题