如果位置发生变化,则float的c-printf的行为会有所不同



我有下面的一段代码:

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应该按照前面提到的顺序打印。有人能解释一下发生了什么行为吗?

您所做的是未定义的行为%p格式说明符承诺您将传入一个指针(特别是void*指针),而将传入double(当将float值传递给可变函数(如printf)时,会将其提升为double)。因此,一旦您不能满足要求,编译器和实现就可以随心所欲,在第二种情况下打印出0而不是85是完全合法的。

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

正如其他人所提到的,您实际上应该使用-Wall选项进行编译(假设GCC或GCC兼容的编译器)。它将帮助您发现这类错误。

printf()需要一个用于格式说明符%p的指针,而您正在传递浮点的。这是未定义的行为。

如果您想打印地址,请传递地址:

printf("%f %p",i, &i);

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

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

您可能遇到了一些未定义的行为;将浮点值打印为指针是完全没有意义的。

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级别,浮点和指针参数是通过不同的寄存器传递的。因此,实现可能会将所涉及的任何寄存器的(未初始化或旧的)内容打印为指针。

最新更新