昔の(事前ANSI)などの予め定義シンボルunix
とvax
それ用にコンパイルされていたものシステムコンパイル時に検出するためのコードを可能にする方法でした。当時、公式の言語標準はありませんでした(K&Rの最初の版の裏にある参考資料を超えて)。複雑なCコードは、通常、#ifdef
システム間の違いを考慮に入れて複雑なsの迷路でした。これらのマクロ定義は、通常、コンパイラ自体によって設定され、ライブラリヘッダーファイルでは定義されていません。実装でどの識別子を使用でき、プログラマ用に予約されているかについての実際のルールはなかったので、コンパイラの作成者は、簡単な名前を自由に使用できunix
、プログラマは自分の目的でこれらの名前を使用しないようにしています。
1989年のANSI C規格では、実装で合法的に事前定義できる記号を制限するルールが導入されました。コンパイラーによって事前定義されたマクロは、2つの下線で始まる名前、または下線の後に大文字が続く名前のみを持つことができ、プログラマーはそのパターンに一致せず、標準ライブラリーでは使用されない識別子を自由に使用できます。
結果として、のようなものを使用する完全に合法なコードをコンパイルすることができないため、事前定義unix
またはlinux
非準拠のコンパイラーint linux = 5;
。
偶然にも、gccはデフォルトでは非準拠ですが、適切なコマンドラインオプションに(かなりよく)準拠させることができます。
gcc -std=c90 -pedantic ... # or -std=c89 or -ansi
gcc -std=c99 -pedantic
gcc -std=c11 -pedantic
詳細については、gccのマニュアルを参照してください。
gccはこれらの定義を将来のリリースで段階的に廃止する予定であるため、それらに依存するコードを記述しないでください。プログラムがLinuxターゲット用にコンパイルされているかどうかを知る必要がある場合__linux__
は、定義されているかどうかを確認できます(gccまたは互換性のあるコンパイラーを使用している場合)。詳細については、GNU Cプリプロセッサのマニュアルを参照してください。
大部分は無関係ですが、David Korn(そう、Korn Shellの作者)による1987 International Obfuscated C Code Contestの "Best One Liner"勝者は、事前定義されたunix
マクロを利用しました。
main() { printf(&unix["\021%six\012\0"],(unix)["have"]+"fun"-0x60);}
表示され"unix"
ますが、マクロ名のスペルとはまったく関係のない理由によります。