函数名周围的括号是啥意思?
Posted
技术标签:
【中文标题】函数名周围的括号是啥意思?【英文标题】:What do the parentheses around a function name mean?函数名周围的括号是什么意思? 【发布时间】:2012-11-16 01:13:57 【问题描述】:在我的一个项目源文件中,我找到了这个 C 函数定义:
int (foo) (int *bar)
return foo (bar);
注意:foo
旁边没有星号,所以它不是函数指针。或者是吗?
递归调用是怎么回事?
【问题讨论】:
不,它不是函数指针——它仍然是一个名为 foo 的常规函数。 这是完整的功能吗? 你有证据表明这个函数被用在了有用的上下文中吗? ...看起来像一些虚拟函数,可能只是为了查看它是否在现有源代码中编译而编写的,应该已被删除。我会删除它(如果这是该函数真正所做的),因为充其量它会是无限循环(我不确定是否允许 C 编译器优化该尾调用以跳转),最坏的情况是堆栈溢出。 C 声明中的括号有助于使语言不明确。快,a(b);
是什么?将b
声明为a
类型的变量?或者使用参数b
调用函数a
?区别在于语法,如果不查找a
的声明信息,您甚至无法知道如何解析它;即那些后缀函数调用括号,或声明符周围的可选括号。
【参考方案1】:
在没有任何预处理器的情况下,foo
的签名相当于
int foo (int *bar)
我看到人们在函数名称周围加上看似不必要的括号的唯一情况是,当同时存在同名的函数和类似函数的宏,并且程序员想要防止宏扩展时。
这种做法一开始可能看起来有点奇怪,但 C 库开创了 providing some macros and functions with identical names 的先例。
这样的一个函数/宏对是isdigit()
。该库可能将其定义如下:
/* the macro */
#define isdigit(c) ...
/* the function */
int (isdigit)(int c) /* avoid the macro through the use of parentheses */
return isdigit(c); /* use the macro */
您的函数看起来与上面的几乎相同,所以我怀疑这也是您的代码中发生的事情。
【讨论】:
这里可能也是这样;我没有寻找宏...而且我不知道宏扩展不会发生在括号内,感谢您指出! @user1859094:再看一遍,几乎可以肯定这就是您的代码中发生的事情。函数内部的foo(bar)
使用的是对应的宏。
@user1859094 宏扩展确实发生在括号内,但类似函数的宏的扩展只有在下一个标记是左括号时才会发生(C99,6.10.3§10),因此@987654327 @ 会被替换,但不会被替换为 (foo) (int *bar)
(foo
之后的下一个标记是 )
)
这样的函数怎么调用?你也会用括号来称呼它吗?例如,这是否可行:(isdigit)(5)
?
@Greg:没错,你就是这么称呼它的。【参考方案2】:
括号并没有改变声明 - 它仍然只是定义一个名为foo
的普通函数。
之所以使用它们,几乎可以肯定是因为定义了一个名为foo
的类似函数的宏:
#define foo(x) ...
在函数声明中使用(foo)
可防止此宏在此处展开。因此,可能发生的情况是,正在定义一个函数 foo()
,其主体从类似函数的宏 foo
扩展而来。
【讨论】:
很好的推论(尽管为此使用括号应该受到法律的惩罚)。 @ugoren:在函数名周围使用括号是防止类函数宏的宏扩展的唯一方法。有时它是必要的工具。 @MichaelBurr,也可以选择不使用同名的宏和函数。我知道你不能总是控制一切,但如果你达到了这个解决方案,我会说有些地方很不对劲。【参考方案3】:括号没有意义。 您显示的代码不过是无限递归。
在定义函数指针时,您有时会看到奇怪的括号,它们确实意味着什么。但这里不是这样。
【讨论】:
显然不是;括号防止宏扩展。查看接受的答案。 @Kevin,我的回答是关于显示的代码,并且是正确的。在这里几乎所有的 C 问题中,假设未知的预处理器定义可以改变一切。在这种情况下,考虑预处理器的答案确实更好,但不会使我的答案不正确。以上是关于函数名周围的括号是啥意思?的主要内容,如果未能解决你的问题,请参考以下文章