首页 > 解决方案 > 为什么函数指针可以带或不带运算符的地址?

问题描述

在《Beginning C from Novice to Professional》一书中,作者在将函数赋值给函数指针时并没有使用运算符的地址。我在编译器上输入了带有和不带有运算符地址的代码,并且两次都按预期编译和执行。为什么在企业/商业环境中会首选这种方式以及哪种方式?

int sum(int, int);

int main(void)
{
    ...
    int (*pfun)(int, int);
    pfun = ∑
    pfun = sum;
    ...
}

int sum(int x, int y)
{
    return x + y;
}

标签: cfunction-pointersaddress-operator

解决方案


这是 C 中函数的一个特性。C 标准说明如下(C11 3.4.1p4)

  1. 函数指示符是具有函数类型的表达式。除非它是运算符的操作数,sizeof运算_Alignof符 65) 或一元运算&符,类型为“函数返回类型”的函数指示符被转换为类型为“指向函数返回类型的指针”的表达式。

sum,函数指示符在任何表达式上下文中,除非前面有&或所述2个运算符被转换为指向函数的指针。当然,在表达式&sum中,结果是一个指向函数的指针。并且 ISO C 不允许sizeof_Alignof应用于函数,因此在任何编译的表达式中,函数指示符要么隐式地,要么在地址运算符的情况下,显式转换为指向函数的指针。

甚至函数调用运算符也 () 要求其操作数是指向函数的指针,因此您可以pfun在不取消引用的情况下调用pfun(1, 2):and in首先sum(1, 2) sum转换为指向函数的指针,然后将函数调用运算符应用于此指针。

有一些编码约定说通过函数指针的调用应该使用解引用运算符*,即(*pfun)(1, 2),同样的赋值写为pfun = ∑

因此,写作(*pfun)(1, 2)不会更清楚地表明它是一个指针,因为相同的语法同样适用于函数指示符,即(*sum)(1, 2);在后者中,sum首先将其转换为指向函数的指针,因为它是*;的操作数 然后取消引用将指向函数的指针再次转换为函数指示符,然后由于它是函数调用运算符的操作数,因此再次将其转换为函数指针。

最后,请注意,pfun 作为函数指针类型的对象&pfun实际上会获得指针变量的地址,这几乎不是您想要的。


推荐阅读