如果位置改变,printf for float的行为会有所不同

Diw*_*rma 4 c floating-point printf

我在下面的一段代码:

float i=85.00;
printf("%f %p",i,i);
Run Code Online (Sandbox Code Playgroud)

打印o/p:

85.00000 (nil)
Run Code Online (Sandbox Code Playgroud)

但是当我改变下面的顺序时:

    float i=85.00;
    printf("%p %f",i,i);
Run Code Online (Sandbox Code Playgroud)

o/p是:

(nil) 0.00000
Run Code Online (Sandbox Code Playgroud)

虽然我希望类似的o/p应按照前面提到的顺序打印.有什么行为可以请任何人解释一下吗?

P.P*_*.P. 8

printf()期望格式说明符的指针,%p而您传递的是浮点.这是未定义的行为.

如果要打印地址,请传递地址:

printf("%f %p",i, &i);
Run Code Online (Sandbox Code Playgroud)

如果您打开警告,您将看到问题:

警告:格式'%p'需要'void*'类型的参数,但参数3的类型为'double'[-Wformat]


Ada*_*eld 8

你正在做的是未定义的行为.该%p格式说明承诺,你传递一个指针(具体为void*指针),而你传递一个double代替(float价值得到提升,以double当传递给可变参数的功能,如printf).因此,只要您不满足要求,编译器和实现就可以随意执行任何操作,并且在第二种情况下打印0而不是85是完全合法的.

可能发生的是编译器正在使用一个调用约定,它将浮点值放在单独的寄存器中(例如x87浮点堆栈或SSE2 SIMD寄存器)而不是堆栈,而像指针这样的整数值会被传递堆栈.因此,当实现看到%p格式说明符时,它会尝试从堆栈中读取参数,而实际上参数实际上是在其他地方.

正如其他人所提到的,你应该真正使用该-Wall选项进行编译(假设GCC或GCC兼容的编译器).它可以帮助您捕获这些错误.

  • @DiwakarSharma这是C99标准的链接,简洁性和精确性之间的良好折衷(C标准随着时间的推移变得越来越长).http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf (2认同)