为什么此代码中每个printf的输出会有所不同?

时间:2012-03-21 18:49:14

标签: c

  

可能重复:
  Why does printf print wrong values?

#include<stdio.h>

int main(int argc, const char *argv[]){
    float f1 = 125.2f;

    printf("\n [%f] [%d] [%g]",f1,f1,f1);
    printf("\n [%f] [%g] [%d]",f1,f1,f1);
    printf("\n [%g] [%f] [%d]",f1,f1,f1);
    printf("\n [%g] [%d] [%f]",f1,f1,f1);
    printf("\n [%d] [%g] [%f]",f1,f1,f1);
    printf("\n [%d] [%f] [%g]",f1,f1,f1);  
    getchar();
}  

虽然使用相同的格式标识符打印相同的变量,但我可以看到每个printf的不同输出。

4 个答案:

答案 0 :(得分:3)

printf不是类型安全的,因此使用不正确的格式描述符会导致未定义的行为

未定义的行为意味着任何可观察的行为都是可能的,因为代码不符合标准规定的规则。

答案 1 :(得分:1)

您的代码会导致未定义的行为。任何事情都可能发生。

根据规范, J.2未定义行为部分:

  

对一个格式化输入/输出函数的调用中的格式参数不足,或者参数没有合适的类型(7.19.6.1,7.19.6.2,7.24.2.1,7.24.2.2)。

因此,您还可以查看参考部分以获取更多信息。在您的情况下,相关位是 7.9.16.1 fprintf函数,第9段:

  

如果转换规范无效,则行为未定义。如果任何参数不是相应转换规范的正确类型,则行为未定义。

7.19.6.3 printf功能:

  

printf 功能相当于 fprintf ,参数 stdout 插入之前 printf 的参数。

答案 2 :(得分:0)

"%d"格式需要int参数。传递float参数(提升为double)会导致未定义的行为。

可能正在发生的事情是printf从堆栈中获取了错误的字节数,但是你花费的时间更好地修复代码而不是弄清楚为什么坏代码在特定代码中行为不端方式。

void main()错了;使用int main(void)。如果某些教科书告诉你void main()是正确的,那么作者就不会很好地掌握这门语言,而是写下它。

答案 3 :(得分:0)

细节将根据机器和编译器而有所不同,但假设float是4个字节,double是8个字节,int是4个字节。

您在堆栈上放置了三个浮点数,这些浮点数被提升为8个字节,总共24个字节。然后你的格式字符串从堆栈中拉出不同数量的字节。所以

  • %f,%d,%g将拉出8,4,8字节
  • %f,%g,%d将拉8,8,4字节
  • %g,%f,%d将拉8,8,4个字节
  • %g,%d,%f将拉出8个,4个,8个字节
  • %d,%g,%f将拉4,8,8个字节
  • %d,%f,%g将拉4,8,8字节

printf的vararg区域中的类型必须与转换运算符所期望的类型匹配。