c - 为什么函数指针声明需要知道参数和返回值的类型?
问题描述
为什么 C 中的函数声明需要知道指向函数的参数和返回值的类型?
c 中的指针声明如下所示:
returnType ( *funcPtrName ) ( paramTypes )
例如foo
下面:
char my_func ( int x )
{
...
}
int main ()
{
char ( *foo ) ( int );
foo = my_func;
foo( 2 );
}
声明指向值的指针时,类型用于确定一个元素的大小(以字节为单位)。例如在 中int* p
,int
告诉编译器 指向的元素p
是sizeof( int )
分开的。该信息用于指针运算。
但是,函数指针指向单个地址,并且不允许使用指针运算。
那么为什么需要额外的信息呢?returnType
包含和paramTypes
仅仅是为了支持编译器的错误检查吗?(例如,在用户分配类型不匹配的函数时提醒用户)。
解决方案
有几个原因。让我们首先考虑返回值。
假设一个程序包含代码y = f(x);
。调用后f
,编译器需要获取它返回的值并赋值给y
。它从哪里获得这个价值?在某些系统中,整数返回值在通用寄存器中传递,而浮点返回值在浮点寄存器中传递。所以编译器无法知道返回值在哪里,除非它知道类型。宽整数,例如long long int
,可以在多个寄存器中传递。小结构可能会在寄存器中返回,而大结构可能会在内存中返回,使用指向调用函数提供的空间的指针,并且需要将其作为隐藏参数传递给被调用函数。
同样,编译器在调用函数时需要知道将参数放在哪里。前几个整数参数可能在通用寄存器中传递,而前几个浮点参数可能在浮点寄存器中传递。任何一种类型的附加参数都可能被压入堆栈。
此外,有时程序员可能会传递一个整数表达式,该函数实际上需要一个浮点参数,例如 in pow(x, 4)
。当编译器知道参数必须是浮点参数时,它可以将其转换为预期的类型。
另一个好处是,当编译器知道类型时,如果参数与预期类型不匹配并且不能隐式转换为预期类型,它可以报错,如果返回类型不匹配,它同样可以报错.