1087

GCCのCプリプロセッサが単語(小文字) を定数として解釈するのはなぜですか?linux1

test.c:

#include <stdio.h>
int main(void)
{       
    int linux = 5;
    return 0;
}

(前処理段階の後に停止) の結果$ gcc -E test.c:

....
int main(void)
{
    int 1 = 5;
    return 0;
}

もちろん、これはエラーを引き起こします。

(ところで:ファイル#define linuxにはありませんstdio.h。)

4

5 に答える 5

193

これは (文書化されていない) "GNU 拡張機能" のようです: [訂正: ようやくドキュメントで言及を見つけました。下記参照。]

次のコマンドは、-dMオプションを使用してすべてのプリプロセッサ定義を出力します。入力「ファイル」は空であるため、事前定義されたマクロが正確に表示されます。標準のubuntuインストールでgcc-4.7.3で実行されました。プリプロセッサが標準対応であることがわかります。合計で、243 個のマクロと;付き-std=gnu99の 240 個のマクロがあります。-std=c99関連性のために出力をフィルタリングしました。

$ cpp --std=c89 -dM < /dev/null | grep linux
#define __linux 1
#define __linux__ 1
#define __gnu_linux__ 1

$ cpp --std=gnu89 -dM < /dev/null | grep linux
#define __linux 1
#define __linux__ 1
#define __gnu_linux__ 1
#define linux 1

$ cpp --std=c99 -dM < /dev/null | grep linux
#define __linux 1
#define __linux__ 1
#define __gnu_linux__ 1

$ cpp --std=gnu99 -dM < /dev/null | grep linux
#define __linux 1
#define __linux__ 1
#define __gnu_linux__ 1
#define linux 1

「gnu 標準」バージョンも#define unix. ( と を使用c11gnu11ても同じ結果が得られます。)

-std=gnu89彼らには理由があったと思いますが、gcc(特に指定しない限りCコードをコンパイルする)のデフォルトのインストールを非準拠にするように思われ、 - この質問のように - 驚くべきことです。名前がアンダースコアで始まらないマクロでグローバル名前空間を汚染することは、準拠した実装では許可されていません。(6.8.10p2: 「その他の事前定義されたマクロ名は、先頭のアンダースコアで始まり、その後に大文字または 2 番目のアンダースコアが続くものとする」が、付録 J.5 (移植性の問題) で述べたように、そのような名前はしばしば事前定義されています。)

私が最初にこの回答を書いたとき、この問題に関するドキュメントをgccで見つけることができませんでしたが、C実装定義の動作でもC拡張でもなく、cppマニュアルセクション3.7.3で最終的に発見しました。それは次のように述べています。

予約済みの名前空間の外にあるすべての定義済みマクロを段階的に廃止しています。新しいプログラムでは絶対に使用しないでください…

于 2013-10-06T16:22:38.773 に答える