这是我正在尝试的代码。我无法理解我得到的输出。为什么输出一些垃圾值而不是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);
}
输出是一些垃圾值。
答案 0 :(得分:4)
为什么输出一些垃圾
因为你撒谎到编译器。
你告诉它foo
是一个指向接受float
的函数的指针......但是然后将它指向一个接受int
的函数。
不要欺骗编译器
答案 1 :(得分:4)
这是未定义的行为。
您正在调用f
,这是一个int
的函数,就像它是一个float
的函数一样。实际行为将取决于平台的调用约定如何工作 - 例如,如果int
和float
参数在同一寄存器或同一堆栈槽中传递,结果将是别名的将10.0f
表示为int
的浮点位模式。另一方面,如果int
和float
以不同方式传递,则结果将是适当寄存器或堆栈槽中的垃圾。
此外,因为这是未定义的行为,编译器可以自由地做任何它喜欢的事情,如果启用了优化器,它可能会这样做。
答案 2 :(得分:4)
在这种情况下,合作者通常会发出警告或错误,例如海湾合作委员会说:
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寄存器(RDI
,RSI
等)传递,而浮点参数在SSE寄存器(XMM0
,XMM1
中传递,等等。)。即使浮点值以某种方式与整数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
答案 3 :(得分:2)
由于未定义的行为。
foo()
之间的调用会将整数10
转换为float
,然后int
将其解释为f()
。
我很确定这个定义不明确。
答案 4 :(得分:1)
由于原型不同。编译器将“10”视为float,并使用其浮点表示来调用f()
,而{{1}}又将其视为ineteger,其二进制表示不具有值“10”。