[解決済み] Cプリプロセッサはなぜ "linux "という単語を定数 "1 "と解釈するのですか?
質問
なぜ
C
のプリプロセッサーは
GCC
という単語を解釈します。
linux
(小文字)を定数
1
?
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
ファイルを作成します)。
解決方法は?
昔は(ANSI以前)、以下のような記号をあらかじめ定義していました。
unix
と
vax
は、コンパイル時にコードがどのシステム用にコンパイルされているかを検出できるようにする方法でした。当時は公式の言語標準がなく(K&Rの初版の巻末にある参考資料以上)、C言語のコードは複雑な迷路のようなものでした。
#ifdef
のように、システム間の差異を許容するためのものです。これらのマクロ定義は、一般にライブラリのヘッダーファイルで定義されるのではなく、コンパイラ自身が設定するものであった。どの識別子を実装で使って、どれをプログラマが使うかといったルールがないため、コンパイラは自由に
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プリプロセッサー・マニュアル
をご覧ください。
全く関係ない余談ですが、1987年の「ベストワン・ライナー」の受賞者は
国際難読化Cコードコンテスト
David Korn (そう、Korn Shell の作者) は、定義済みの
unix
マクロを使用しています。
main() { printf(&unix["\021%six\012\0"],(unix)["have"]+"fun"-0x60);}
印刷されます
"unix"
しかし、その理由はマクロ名のスペルとは全く関係ありません。
関連
-
[解決済み】ENOENTが「そのようなファイルやディレクトリはありません」という意味であるのはなぜですか?
-
未定義の `__isoc99_sscanf' への参照
-
[解決済み] PTHREAD_MUTEX_INITIALIZER vs pthread_mutex_init ( &mutex, param )
-
[解決済み] C言語では「?」演算子は何をするのですか?
-
[解決済み] 配列の場合、なぜ a[5] == 5[a] になるのでしょうか?
-
[解決済み] 難読化Cコードコンテスト2006。sykes2.cの解説をお願いします。
-
[解決済み] Linux, Bashで、現在の時刻をEpochからの秒数で取得する。
-
[解決済み] C 言語の配列へのポインタ/ポインタの配列の曖昧さ解消
-
[解決済み] なぜ16進数には0xがつくのですか?
-
[解決済み] 講師が書いたC言語のファイルは、なぜ最初の行に#が一つ付いているのですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
libc++abi.dylib: NSException タイプの捕捉されない例外で終了するエラー
-
C++の配列コピー
-
ポインタ定数および定数ポインタ
-
[解決済み] C言語の書式指定子 %ul と %lu の違いは何ですか?
-
[解決済み] C言語の**はどういう意味ですか?
-
[解決済み] C言語のコードで「:-!」とは何ですか?
-
[解決済み] C言語における「static」の意味とは?
-
[解決済み] Cプリプロセッサはなぜ "linux "という単語を定数 "1 "と解釈するのですか?
-
[解決済み] C言語でファイルサイズを取得するには?[重複]する
-
[解決済み] 2次元配列の反復処理において、ループの順序がパフォーマンスに影響するのはなぜですか?