5

次のCプログラムを検討してください(二重の副作用の問題は無視してください)。

#define max(a, b) (a>b?a:b)

int main(void){
    int max = max(5,6);
    return max;
}

GCCプリプロセッサはこれを次のように変換します。

int main(void){
    int max = (5>6?5:6);
    return max;
}

maxとの間の意図しない衝突について心配する必要がないので、これは非常に便利ですmax()GCCマニュアルには次のように書かれています。

関数のようなマクロは、その名前の後に括弧のペアが付いている場合にのみ展開されます。名前だけを書くとそのままになります

これは標準化されたものですか、それとも慣例によって行われたものですか?

4

1 に答える 1

5

はい、ここでの動作は明確に定義されています。

マクロmaxは関数のようなマクロです(つまり、マクロを定義すると、その名前の直後に左括弧が続き、引数を取ります)。

コードの後半での使用は、の使用の後に左括弧が続くmax場合にのみ、そのマクロを呼び出します。maxしたがって、これらはmaxマクロを呼び出しません。

int max;
max = 42;

しかし、これらはすべてmaxマクロを呼び出します。

max(1, 2)
max (1, 2)
max
(
    1, 2
)
max()

(引数の数がパラメーターの数と一致しないため、最後の行の形式が正しくないことに注意してください。ただし、これはマクロ呼び出しであり、コンパイルエラーが発生します。)

この動作は、C言語標準によって義務付けられています。C99§6.10.3/10は、関数のようなマクロが定義された後、

関数のようなマクロ名の後続の各インスタンスの後(に次の前処理トークンとしてaが続くと、定義内の置換リスト(マクロの呼び出し)によって置き換えられる前処理トークンのシーケンスが導入されます。

于 2012-06-11T16:48:10.847 に答える