我在下面的代码:
float i=85.00;
printf("%f %p",i,i);
打印o / p:
85.00000 (nil)
但是当我改变下面的顺序时:
float i=85.00;
printf("%p %f",i,i);
o / p是:
(nil) 0.00000
虽然我希望按照上面提到的顺序打印类似的o / p。 任何人都可以解释一下这种行为是什么?
答案 0 :(得分:8)
printf()
期望格式说明符%p
的指针,而您传递浮点数的值。这是未定义的行为。
如果要打印地址,请传递地址:
printf("%f %p",i, &i);
如果您打开警告,则会发现问题:
警告:格式'%p'需要'void *'类型的参数,但参数3 类型为'double'[-Wformat]
答案 1 :(得分:8)
您正在做的是未定义的行为。 %p
格式说明符承诺您传入一个指针(特别是void*
指针),而您传递的是double
,而float
值会被提升传递给double
等可变函数时传递给printf
。因此,只要您不满足要求,编译器和实现就可以随意执行任何操作,并且在第二种情况下打印出0而不是85是完全合法的。
可能发生的事情是编译器正在使用一个调用约定,它将浮点值放在单独的寄存器中(例如x87浮点堆栈或SSE2 SIMD寄存器)而不是堆栈,而整数值就像指针一样在堆栈上传递。因此,当实现看到%p
格式说明符时,它会尝试从堆栈中读取参数,而实际上参数实际上是在其他地方。
正如其他人所提到的,你应该真正使用-Wall
选项进行编译(假设是GCC或GCC兼容的编译器)。它可以帮助你发现这些错误。
答案 2 :(得分:3)
你可能会遇到一些undefined behavior;打印浮动作为指针绝对没有意义。
GCC 4.8调用gcc -Wall
正确警告你:
dwakar.c:5:3: warning: format '%p' expects argument of type 'void *',
but argument 3 has type 'double' [-Wformat=]
printf("%f %p",i,i);
^
因此,请使用gcc -Wall
编译代码并更正代码,直到没有给出警告为止。
请注意,在ABI级别,浮点和指针参数通过不同的寄存器传递。因此,实现可能会打印为指针所涉及的任何寄存器的(未初始化的或旧的)内容。