为什么函数指针可以带或不带运算符地址使用?
Why can function pointers be used with or without the address of operator?
在书"Beginning C from Novice to Professional"中,作者在将函数赋值给函数指针时没有使用运算符的地址。我在我的编译器上输入了带有和不带有运算符地址的代码,并且两次都按预期编译和执行。为什么会这样,在 enterprise/business 设置中首选哪种方式?
int sum(int, int);
int main(void)
{
...
int (*pfun)(int, int);
pfun = ∑
pfun = sum;
...
}
int sum(int x, int y)
{
return x + y;
}
这是 C 函数的一个特点。C 标准规定如下 (C11 3.4.1p4):
- A function designator is an expression that has function type. Except when it is the operand of the
sizeof
operator, the _Alignof
operator, 65) or the unary &
operator, a function designator with type ''function returning type'' is converted to an expression that has type ''pointer to function returning type''.
即作为函数指示符的 sum
在 any 表达式上下文中,除非前面有 &
或上述 2 个运算符被转换为指向函数的指针。当然在表达式 &sum
中,结果是一个指向函数的指针。并且 ISO C 不允许将 sizeof
或 _Alignof
应用于函数,因此在编译的 any 表达式中,函数指示符要么是隐式的,要么是在地址运算符的情况,显式转换为指向函数的指针。
甚至函数调用运算符 ()
要求它的操作数是一个函数指针,因此您可以在不取消引用的情况下调用 pfun
:pfun(1, 2)
;而在sum(1, 2)
中sum
是先转换为函数指针,然后函数调用运算符作用于这个指针。
有编码约定说通过函数指针的调用应该使用取消引用运算符 *
,即 (*pfun)(1, 2)
,同样,赋值应该写成 pfun = ∑
。
因此,写成 (*pfun)(1, 2)
并不能更清楚地表明它是一个指针,因为相同的语法同样适用于函数指示符,即 (*sum)(1, 2)
;在后者中,sum
首先转换为指向函数的指针,因为它是 *
的操作数;然后解引用再次将指向函数的指针转换为函数指示符,然后由于它是函数调用运算符的操作数,因此再次转换为函数指针。
最后,注意pfun
作为函数指针类型的对象,&pfun
实际上会得到指针变量的地址,这几乎是从来没有你想要的。
在书"Beginning C from Novice to Professional"中,作者在将函数赋值给函数指针时没有使用运算符的地址。我在我的编译器上输入了带有和不带有运算符地址的代码,并且两次都按预期编译和执行。为什么会这样,在 enterprise/business 设置中首选哪种方式?
int sum(int, int);
int main(void)
{
...
int (*pfun)(int, int);
pfun = ∑
pfun = sum;
...
}
int sum(int x, int y)
{
return x + y;
}
这是 C 函数的一个特点。C 标准规定如下 (C11 3.4.1p4):
- A function designator is an expression that has function type. Except when it is the operand of the
sizeof
operator, the_Alignof
operator, 65) or the unary&
operator, a function designator with type ''function returning type'' is converted to an expression that has type ''pointer to function returning type''.
即作为函数指示符的 sum
在 any 表达式上下文中,除非前面有 &
或上述 2 个运算符被转换为指向函数的指针。当然在表达式 &sum
中,结果是一个指向函数的指针。并且 ISO C 不允许将 sizeof
或 _Alignof
应用于函数,因此在编译的 any 表达式中,函数指示符要么是隐式的,要么是在地址运算符的情况,显式转换为指向函数的指针。
甚至函数调用运算符 ()
要求它的操作数是一个函数指针,因此您可以在不取消引用的情况下调用 pfun
:pfun(1, 2)
;而在sum(1, 2)
中sum
是先转换为函数指针,然后函数调用运算符作用于这个指针。
有编码约定说通过函数指针的调用应该使用取消引用运算符 *
,即 (*pfun)(1, 2)
,同样,赋值应该写成 pfun = ∑
。
因此,写成 (*pfun)(1, 2)
并不能更清楚地表明它是一个指针,因为相同的语法同样适用于函数指示符,即 (*sum)(1, 2)
;在后者中,sum
首先转换为指向函数的指针,因为它是 *
的操作数;然后解引用再次将指向函数的指针转换为函数指示符,然后由于它是函数调用运算符的操作数,因此再次转换为函数指针。
最后,注意pfun
作为函数指针类型的对象,&pfun
实际上会得到指针变量的地址,这几乎是从来没有你想要的。