1

gcc が次のような奇妙な関数定義をサポートしていることがわかりました。

static void add_define P3(char *, name, int, nargs, char *, exps)

-D__USE_FIXED_PROTOTYPES__ でコンパイルします。また、vim のタグリスト プラグインでは正しい結果が得られませんでした。ctags の man ページで調べようとしましたが、見つかりませんでした。

編集 はい、これは奇妙です。マクロは

#define P3(t1, v1, t2, v2, t3, v3) (t1 v1, t2 v2, t3 v3)

コメントは、これが

ANSI/K&R 互換のもの。

AIX の c コンパイラである xlc をスイートにする予定です。

4

1 に答える 1

4

マクロ定義を次のように使用します。

#define P3(t1, v1, t2, v2, t3, v3) (t1 v1, t2 v2, t3 v3)

この宣言:

static void add_define P3(char *, name, int, nargs, char *, exps);

(末尾にセミコロンを追加しました) は次のように展開されます。

static void add_define(char *name, int nargs, char *exps);

これは完全に通常の関数プロトタイプです (末尾にセミコロンがあると仮定します)。

おそらく、そのマクロの代替バージョンがあり、次のようなものです。

#define P3(t1, v1, t2, v2, t3, v3) \
    (v1, v2, v3) \
    t1 v1; \
    t2 v2; \
    t3 v3;

それは次のように展開されます:

static void add_define(name, nargs, exps)
char *name;
int nargs;
char *exps

これは、K&R スタイルの非プロトタイプ関数宣言です。

おそらく次のようなものがあります:

#ifdef __STDC__
#define P3(t1, v1, t2, v2, t3, v3) (t1 v1, t2 v2, t3 v3)
#else
#define P3(t1, v1, t2, v2, t3, v3) \
    (v1, v2, v3) \
    t1 v1; \
    t2 v2; \
    t3 v3;
#endif

同様のマクロ P0、P1、P2 などと一緒に、異なる数のパラメータに対応します。または、質問で暗示しているように、ユーザー定義マクロ__USE_FIXED_PROTOTYPES__ではなく__STDC__.

これにより、単一の宣言を最新のプロトタイプまたは K&R スタイルの宣言に自動的に拡張できます。後者は、非常に古い ANSI 以前のコンパイラでのみ必要になります。

タイトルの質問に答えるために(ついに!)、ctags前処理されていないCソースで動作します。GNU で簡単な実験をしてみるとctags、基本的な構文を覆い隠すマクロの解釈について、GNU が特に賢いわけではないことがわかります。マクロ定義自体のタグエントリを生成しますが、認識しません

static void add_define P3(char *, name, int, nargs, char *, exps) {
    /* ... */
}

関数定義として。(プリプロセッサを介してソース ファイルを実行することもできますが、その場合、タグは前処理されたファイルを参照するため、特に有用ではありません。) 原則として、プリプロセッサを含む完全な C 構文ctags を理解している必要があります。実際にはそうではありません。

ソース ファイルのタグを生成したい場合ctagsは、マクロを削除して、認識可能なプロトタイプを作成する必要があります。変更されたソースを ANSI 以前のコンパイラでコンパイルすることはできませんが、最近ではそれが問題になることはほとんどありません。これを行う立場にある場合、結果のコードは保守が容易になるはずです。

または、 によって生成される出力ctagsはかなり単純なので、関連するタグを手動でファイルに追加することはそれほど難しくありませんtags(ただし、自動的に維持するのは難しい場合があります)。

于 2012-12-23T05:14:49.967 に答える