関数名の括弧はどういう意味ですか?


214

プロジェクトのソースファイルの1つで、次のC関数の定義を見つけました。

int (foo) (int *bar)
{
    return foo (bar);
}

注:の横にアスタリスクがないfooため、関数ポインターではありません。またはそれは?再帰呼び出しで何が起こっているのですか?


7
いいえ、それは関数ポインタではありません-fooという名前の通常の関数です。
Nemanja Boric、

これは完全な機能ですか?
asheeshr

2
この関数が有用なコンテキストで使用されているという証拠はありますか?
moooeeeep

1
...既存のソースでコンパイルされるかどうかを確認するために単に作成されたダミー関数のように見え、削除されているはずです。スタックオーバーフローが最悪の場合は、せいぜい無限ループ(Cコンパイラーがジャンプの末尾呼び出しを最適化できるかどうかわからない)なので、それを削除します(それが実際に機能する場合)。
ハイド

3
C宣言の括弧は、言語があいまいであることを曖昧にするのに役立ちます。クイック、何a(b);ですか?b型の変数としての宣言a?またはa引数付きの関数の呼び出しbですか?違いは構文であり、の宣言情報を調べないと、構文解析の方法すらわからないa。つまり、後置関数呼び出しの括弧、または宣言子を囲むオプションの括弧です。
Kaz

回答:


329

進行中のプリプロセッサが何もない場合、fooの署名は

int foo (int *bar)

関数名の周りに不要に見える括弧を置く人々を見た唯一の状況は、同じ名前の関数と関数のようなマクロの両方があり、プログラマーがマクロの展開を防ぎたい場合です。

このやり方は最初は少し奇妙に思えるかもしれませんが、Cライブラリは、同じ名前のマクロと関数をいくつか提供することで先例を定めています

そのような関数とマクロのペアの1つは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 */
}

あなたの関数は上記とほとんど同じに見えるので、これもあなたのコードで起こっていることだと思います。


2
ここでもそうかもしれません。私はマクロを探していませんでした...そして、マクロ展開が括弧内で行われないことを知りませんでした、それを指摘してくれてありがとう!
user1859094

13
@ user1859094:再確認すると、これはほぼ確実にコードで起こっていることです。foo(bar)関数の内部は対応するマクロを使用しています。
NPE、2012年

78
@ user1859094マクロ展開は括弧内で行われますが、関数のようなマクロの展開は、次のトークンが左括弧(C99、6.10.3§10)である場合にのみ行わfoo (int* bar)れるため、置き換えられません(foo) (int *bar)(次のトークンは置き換えられません)後fooです)
のVirgile

4
そのような関数はどのように呼び出されますか?括弧も付けて呼びますか?たとえば、これは機能します(isdigit)(5)か?
gcochard

4
@グレッグ:そうだね、まさにその通りだ。
NPE

37

括弧は宣言を変更しません-それはまだと呼ばれる通常の関数を定義しているだけfooです。

それらが使用された理由はほぼfoo定義されたと呼ばれる関数のようなマクロがあるためです:

#define foo(x) ...

(foo)関数宣言で使用すると、このマクロがここで展開されなくなります。したがって、起こりそうなことはfoo()、関数のようなマクロから本体が展開されて関数が定義されていることfooです。


5
素敵な控除(この目的で括弧を使用することは法律で罰せられるべきですが)。
ugoren

3
@ugoren:関数名の前後に括弧を使用することが、関数のようなマクロのマクロ展開を防ぐ唯一の方法です。時にはそれは必要なツールです。
Michael Burr

7
@MichaelBurr、同じ名前のマクロと関数を持たないオプションもあります。あなたはいつもすべてを制御できるわけではないことを知っていますが、この解決策に到達した場合、私は何かが非常に間違っていると思います。
ugoren

-3

括弧は意味がありません。
表示するコードは、無限の再帰にすぎません。

関数ポインタを定義するとき、何かを意味する奇妙な括弧が見つかることがあります。しかし、ここではそうではありません。


6
明らかにそうではありません。括弧はマクロの展開を防ぎます。受け入れられた答えを見てください。
ケビン

12
@Kevin、私の答えは、示されているコードに関するものであり、それに対して正しいです。ここでのほとんどすべてのCの質問では、未知のプリプロセッサー定義がすべてを変更できると想定しています。この場合、プリプロセッサーを考慮した答えは確かに優れていますが、私の答えが間違っているわけではありません。
ugoren
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.