为什么函数指针声明需要知道参数的类型和返回值?

Jet*_*lue 0 c compiler-construction pointers function-pointers static-typing

为什么C中的函数声明需要知道指向函数的参数的类型和返回值?

c中的指针声明编写如下:

returnType ( *funcPtrName ) ( paramTypes )
Run Code Online (Sandbox Code Playgroud)

例如foo下面:

char my_func ( int x )
{
    ...
}


int main ()
{
    char ( *foo ) ( int );

    foo = my_func;

    foo( 2 );
}
Run Code Online (Sandbox Code Playgroud)

在声明一个指向值的指针时,该类型用于确定一个元素的大小(以字节为单位)。例如int* p,中的int告诉编译器指向的元素psizeof( int )分开的。此信息用于指针算术。

但是,函数指针指向单个地址,并且不允许进行指针算术运算。

那么为什么需要额外的信息呢?是returnTypeparamTypes仅作编译器所支持的错误检查的目的是什么?(例如,在用户分配类型不匹配的功能时提醒用户)。

Eri*_*hil 5

有几个原因。让我们首先考虑返回值。

假设程序包含代码y = f(x);。调用后f,编译器需要获取返回的值并将其分配给y。它从哪里获得价值?在某些系统中,整数返回值在通用寄存器中传递,而浮点返回值在浮点寄存器中传递。因此,除非知道类型,否则编译器无法知道返回值在哪里。诸如的宽整数long long int可能会在多个寄存器中传递。小型结构可能会在寄存器中返回,而大型结构可能会在内存中返回,这需要使用指针来分隔调用函数提供的空间,并且要求将其作为隐藏参数传递给被调用函数。

同样,编译器在调用函数时需要知道将参数放在哪里。前几个整数参数可能会在常规寄存器中传递,而前几个浮点参数可能会在浮点寄存器中传递。两种类型的其他参数都可能被压入堆栈。

此外,有时程序员可能会传递一个整数表达式,该函数实际上需要一个浮点参数,例如in pow(x, 4)。当编译器知道参数必须是浮点参数时,它可以将其转换为预期的类型。

另一个好处是,当编译器知道类型时,如果参数与期望的类型不匹配并且无法隐式转换为期望的类型,则可以报告错误;如果返回的类型不匹配,则可以类似地报告错误。 。