简体   繁体   English

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

[英]function pointers with different prototypes in c

Here is the code i was trying.I could not comprehend the output i got.Why is output some garbage value here and not 10? 这是我正在尝试的代码。我无法理解我得到的输出。为什么在这里输出一些垃圾值而不是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);
}

Output is some garbage value. 输出是一些垃圾值。

Why is output some garbage 为什么输出一些垃圾

Because you lie to the compiler. 因为您对编译器撒谎。

You tell it foo is a pointer to a function that accepts a float ... but then point it to a function that accepts an int . 您告诉它foo是指向接受float的函数的指针,但是将其指向接受int的函数。

Don't lie to the compiler 不要对编译器撒谎

This is undefined behaviour. 这是未定义的行为。

You're calling f , which is a function taking an int , as if it were a function taking a float . 您正在调用f ,它是一个带有int的函数,就好像它是一个带有float的函数。 The actual behaviour will depend on how the calling conventions of your platform work - for example, if int and float parameters are passed in the same register or the same stack slot the result will be that of aliasing the floating-point bit pattern representing 10.0f as an int . 实际行为将取决于平台的调用约定如何工作-例如,如果将intfloat参数传递到同一寄存器或同一堆栈插槽中,则结果将是别名表示10.0f的浮点位模式作为一个int If on the other hand int and float are passed differently the result will be whatever garbage was in the appropriate register or stack slot. 另一方面,如果intfloat的传递方式不同,则结果将是相应寄存器或堆栈插槽中的垃圾内容。

Also, because this is undefined behaviour the compiler is at liberty to do whatever it likes, and if the optimiser is enabled it may well do. 另外,由于这是未定义的行为,因此编译器可以自由执行其喜欢的任何事情,并且如果启用了优化程序,则编译器也可能会这样做。

Compiers usually emit warnings or errors in this case, eg GCC says: 在这种情况下,编译器通常会发出警告或错误,例如,GCC表示:

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

Intel C Compiler is more verbose: 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;
                     ^

Besides possible conversion of argument value 10 to floating point, there is another option if you are running on a 64-bit machine - calling convention. 除了可能将参数值10转换为浮点数外,如果您在64位计算机上运行,​​还有另一种选择-调用约定。 Integer arguments are passed through the regular integer CPU registers ( RDI , RSI , etc.) while floating-point arguments are passed in the SSE registers ( XMM0 , XMM1 , etc.). 整数参数通过常规整数CPU寄存器( RDIRSI等)传递,而浮点参数在SSE寄存器( XMM0XMM1等)中传递。 Even if somehow the floating point value was compatible with the integer one, the called function will receive its argument in different register ( XMM0 ) than the one it will consult for the value ( RDI ). 即使浮点值与整数1兼容,被调用函数也将在其寄存器( XMM0 )中接收其自变量,而不是为其查询值( RDI )。

On a 32-bit machine both integer and floating point arguments are passed on the stack. 在32位计算机上,整数和浮点参数都在堆栈上传递。 What you end up with is 1092616192 which is just 10.0 in IEEE 754 single-precision floating point representation: 您最终得到的是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

Because of undefined behavior. 由于未定义的行为。

The call through foo() converts the integer 10 to float , which is then interpreted as an int by f() . 通过foo()的调用将整数10转换为float ,然后由f()解释为int

I'm pretty sure this isn't well-defined. 我很确定这不是很好的定义。

Because of the different prototypes. 由于原型不同。 The compiler treats "10" as a float, and uses its floating-point representation to call f() , which in turn treats it as an ineteger, whose binary representation does not have the value "10". 编译器将“ 10”视为浮点型,并使用其浮点表示形式调用f() ,而f()依次将其视为一个ineteger,其二进制表示形式的值不为“ 10”。

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

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