0

这是我正在尝试的代码。我无法理解我得到的输出。为什么在这里输出一些垃圾值而不是 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);
}

输出是一些垃圾值。

4

5 回答 5

4

为什么输出一些垃圾

因为你对编译器撒谎。

你告诉它foo是一个指向接受 a 的函数的指针,float然后将它指向一个接受 a 的函数int

不要对编译器撒谎

于 2012-06-25T12:15:18.550 回答
4

这是未定义的行为。

您正在调用f,这是一个接受 a 的函数int,就好像它是一个接受 a 的函数一样float。实际行为将取决于平台的调用约定如何工作 - 例如,如果intfloat参数在同一个寄存器或同一个堆栈槽中传递,结果将是别名表示10.0fint. 另一方面int,如果float以不同的方式传递,则结果将是适当的寄存器或堆栈槽中的任何垃圾。

此外,因为这是未定义的行为,编译器可以自由地做它喜欢的任何事情,如果启用了优化器,它可能会做。

于 2012-06-25T12:18:30.103 回答
4

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

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

英特尔 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 位机器上,整数和浮点参数都在堆栈上传递。你最终得到的是1092616192IEEE 10.0754 单精度浮点表示:

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
于 2012-06-25T12:33:29.173 回答
2

因为未定义的行为。

调用 throughfoo()将整数转换10float,然后将其解释为intby f()

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

于 2012-06-25T12:13:58.750 回答
1

因为原型不同。编译器将“10”视为浮点数,并使用其浮点表示来调用f(),而后者又将其视为整数,其二进制表示不具有值“10”。

于 2012-06-25T12:14:58.533 回答