这是一本旧学校书的摘录:C Traps and Pitfalls,第二章。
(*(void(*)())0)();
相当于更现代:
typedef void (*function_pointer) ();
(*(function_pointer)0)();
我想要一些帮助,以便更好地了解typedef下面的第二个代码行是什么。我该如何解释这种奇怪的语法?
答案 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
。)