繁体   English   中英

C中具有不同原型的函数指针

[英]function pointers with different prototypes in c

这是我正在尝试的代码。我无法理解我得到的输出。为什么在这里输出一些垃圾值而不是10?

#include<stdio.h>
#include<string.h>
void f(int);
void (*foo)(float)=f;
int main()
{

  foo(10);
   return 0;

}

void f(int i)
{
   printf("%d\n",i);
}

输出是一些垃圾值。

为什么输出一些垃圾

因为您对编译器撒谎。

您告诉它foo是指向接受float的函数的指针,但是将其指向接受int的函数。

不要对编译器撒谎

这是未定义的行为。

您正在调用f ,它是一个带有int的函数,就好像它是一个带有float的函数。 实际行为将取决于平台的调用约定如何工作-例如,如果将intfloat参数传递到同一寄存器或同一堆栈插槽中,则结果将是别名表示10.0f的浮点位模式作为一个int 另一方面,如果intfloat的传递方式不同,则结果将是相应寄存器或堆栈插槽中的垃圾内容。

另外,由于这是未定义的行为,因此编译器可以自由执行其喜欢的任何事情,并且如果启用了优化程序,则编译器也可能会这样做。

在这种情况下,编译器通常会发出警告或错误,例如,GCC表示:

program.c:4: warning: initialization from incompatible pointer type

Intel C编译器更详细:

program.c(4): warning #144: a value of type "void (*)(int)" cannot be used to initialize an   entity of type "void (*)(float)"
  void (*foo)(float)=f;
                     ^

除了可能将参数值10转换为浮点数外,如果您在64位计算机上运行,​​还有另一种选择-调用约定。 整数参数通过常规整数CPU寄存器( RDIRSI等)传递,而浮点参数在SSE寄存器( XMM0XMM1等)中传递。 即使浮点值与整数1兼容,被调用函数也将在其寄存器( XMM0 )中接收其自变量,而不是为其查询值( RDI )。

在32位计算机上,整数和浮点参数都在堆栈上传递。 您最终得到的是1092616192 ,在IEEE 754单精度浮点表示中仅为10.0

1092616192 = 0|10000010|01000000000000000000000
             | |        |
             | |        +---> significand = 1 + 2^(-2) = 1.25
             | |
             | +------------> exponent = 130 - 127 = +3
             |
             +--------------> sign = 0 (positive)

1.25 * 2^3 = 1.25 * 8 = 10.0

由于未定义的行为。

通过foo()的调用将整数10转换为float ,然后由f()解释为int

我很确定这不是很好的定义。

由于原型不同。 编译器将“ 10”视为浮点型,并使用其浮点表示形式调用f() ,而f()依次将其视为一个ineteger,其二进制表示形式的值不为“ 10”。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM