Cの名前空間に関する覚え書き
「新版C言語プログラミングレッスン 文法編」を読んで、Cにも名前空間があることを、恥ずかしながら初めて知った。今回は、Cの名前空間についてのまとめを、いつものように行うこととする。
6.2.3 識別子の名前空間
翻訳単位中のある位置で特定の識別子の複数の宣言が可視である場合、構文的な文脈によって異なった実体への参照を区別する。すなわち、識別子を様々に分類するため、次に示す種類の名前空間(name space)が存在する。
- ラベル名(label name) (中略)。
- 構造体、共用体及び列挙体のタグ(tag) (中略)。
- 構造体又は共用体のメンバ(member)。 (中略)。
- その他のすべての識別子(通常の宣言子で宣言されたもの、又は列挙定数として宣言されたもの)。これらを通常の識別子(ordinary identifier)と呼ぶ。
「JISX3010 プログラム言語C 2003/12/20最新改正版」 (http://www.jisc.go.jp/app/JPS/JPSO0020.htmlより、X3010で検索)、pp. 23-24
同じ識別子が異なる実体を指し示すのは、それらが異なる有効範囲をもつときか、又は異なる名前空間に属するときかのいずれかとする。
Ibid、p.22
これはつまり、同じスコープ(名前の有効範囲)内でも、名前空間が別々であれば、同じ識別子名を用いることができる、ということだ。例えば、あるスコープにおいて、構造体タグ名と変数名*1が同じであっても、両者は区別可能なのである。
次のプログラムはエラーを生じない。
/* スコープが同じで、名前空間が異なる */ struct var { int memb; }; struct var var; /* 構造体タグ名と変数名(通常の識別子)が同じでもOK */
次のようなよく見られるコードがエラーを出さないのも、同じ理由による。
/* スコープが同じで、名前空間が異なる */ typedef struct node { struct node *next; } node; /* 構造体タグ名とtypedef名(通常の識別子)が同じでもOK */
「ラベル名、タグ、メンバ」以外の識別子名、つまり「変数名、関数名、enumの列挙子、typedef名」は、全て「通常の識別子」の名前空間に入っていることに注意すること。
同じスコープで名前空間も同じであれば、当然エラーが発生する。
/* スコープが同じで、名前空間も同じ */ typedef int var; var var; /* typedef名と変数名が同じなので、エラー */ int main(){ }
*1:変数名は「通常の識別子」である。