C语言函数指针奇怪的语法

时间:2017-03-02 18:31:17

标签: c function-pointers

这是一本旧学校书的摘录:C Traps and Pitfalls,第二章。

(*(void(*)())0)();

相当于更现代:

typedef void (*function_pointer) ();
(*(function_pointer)0)();

我想要一些帮助,以便更好地了解typedef下面的第二个代码行是什么。我该如何解释这种奇怪的语法?

1 个答案:

答案 0 :(得分:0)

与对象指针(包括数组)不同,&*运算符在处理函数指针时是可选的。有些人还是喜欢使用它们,认为它使得代码对函数指针的使用更加清晰。我个人不同意,只是使用名称。

因此:

// given
typedef int (* F) (void);
extern int foo (void);

// the following definitions are all identical:
F fp1 = foo;
F fp2 = &foo;
F fp3 = *foo;

// as are the following call expressions:
foo ();
(&foo) ();
(*foo) ();
fp1 ();
(*fp1) ();
(******* fp1) ();

与数组的情况非常相似,在任何表达式总是中用作值的函数会衰减到函数指针,除非用作{{>> 的 immediate 参数1}}。从技术上讲,这也包括函数调用表达式,所以括号左边的东西总是一个函数指针,即使调用直接指向一个静态命名的函数(即表达式&)。类似地,取消引用带有foo ()的函数指针会检索函数的“值”,但函数“值”唯一能做的就是立即衰减回指针,这就是为什么你可以用尽可能多的星号取消引用它的原因。你喜欢。

这些都不会在运行时产生任何影响;它只影响表达式的类型

使用函数指针作为*的直接参数将执行其他操作:但是它将创建一个标准的双指针(指向的指针),或者如果函数表达式不是左值,则语法无效。您也可以在某些可选星号前面加上&的一个级别,在这种情况下,它会阻止&运算符的结果立即衰减,而是明确地转换类型,继续实现绝对没有。

因此,从问题中编写代码的更简单(和IMO更清晰)的方法如下:

*

大多数明星什么都不做,如果没有它们,代码就更容易阅读。这也表明问题表达式的第二行实际上是两个操作(通常在机器级别都是无操作) - 首先它将typedef void (*function_pointer) (); // 1 - direct ((function_pointer)0)(); // 2 - intermediate variable function_pointer fp = (function_pointer)0; fp (); 转换为类型{{1} },然后然后它应用0。 (然后在第三个no-op中,它再次在括号外消除function_pointer。)