名前空間を持つことは、ほとんどの言語で簡単に思えます。しかし、私が知る限り、ANSI Cはそれをサポートしていません。何故なの?将来の標準に含める予定はありますか?
Cには名前空間があります。 1つは構造タグ用で、もう1つは他のタイプ用です。次の定義を考慮してください。
struct foo
{
int a;
};
typedef struct bar
{
int a;
} foo;
最初のものにはtag fooがあり、後者はtypedefでfoo型になります。それでも名前の衝突は起こりません。これは、構造タグとタイプ(組み込みタイプとtypedef'edタイプ)が別々の名前空間に存在するためです。
Cが許可しないのは、new名前空間を自由に作成することです。 Cは言語でこれが重要と見なされる前に標準化されました。名前空間を追加すると、正しく機能するには名前のマングリングが必要になるため、下位互換性も脅かされます。これは哲学ではなく専門性に起因すると考えられます。
編集:JeremyPは幸いなことに私を修正し、私が逃した名前空間に言及しました。ラベルおよび構造体/ユニオンメンバの名前空間もあります。
完全を期すために、Cのネームスペースから得られる「メリット」を実現する方法がいくつかあります。
私のお気に入りのメソッドの1つは、ライブラリ/などへのインターフェイスであるメソッドポインターの束を格納する構造を使用することです。
次に、この構造体のexternインスタンスを使用して、ライブラリ内ですべての関数をポイントして初期化します。これにより、クライアントの名前空間(グローバルスコープのextern変数、1つの変数と場合によっては数百のメソッド以外)を踏むことなく、ライブラリ内の名前をシンプルに保つことができます。
いくつかの追加のメンテナンスが含まれますが、私はそれが最小限であると感じています。
以下に例を示します。
/* interface.h */
struct library {
const int some_value;
void (*method1)(void);
void (*method2)(int);
/* ... */
};
extern const struct library Library;
/* interface.h */
/* interface.c */
#include "interface.h"
void method1(void)
{
...
}
void method2(int arg)
{
...
}
const struct library Library = {
.method1 = method1,
.method2 = method2,
.some_value = 36
};
/* end interface.c */
/* client code */
#include "interface.h"
int main(void)
{
Library.method1();
Library.method2(5);
printf("%d\n", Library.some_value);
return 0;
}
/* end */
の用法 。構文は、従来のLibrary_function()Library_some_valueメソッドに対して強力な関連付けを作成します。ただし、いくつかの制限があり、マクロを関数として使用することはできません。
Cには名前空間があります。構文はnamespace_name
です。 general_specific_name
のようにネストすることもできます。また、名前空間名を毎回書き込むことなく名前にアクセスできるようにしたい場合は、関連するプリプロセッサマクロをヘッダーファイルに含めます。
#define myfunction mylib_myfunction
これは名前のマングリングや特定の言語が名前空間を提供することを約束する他の残虐行為よりもずっときれいです。
歴史的に、Cコンパイラは名前をマングルしません(Windowsで行いますが、cdecl
呼び出し規約のマングリングはアンダースコアプレフィックスの追加のみで構成されます)。
これにより、他の言語(アセンブラーを含む)のCライブラリーを簡単に使用できるようになり、C++ APIのextern "C"
ラッパーがよく表示される理由の1つになります。
歴史的な理由だけです。当時は名前空間のようなものを持っているとは誰も考えていませんでした。また、彼らは本当に言語をシンプルにしようとしていました。彼らは将来それを持っているかもしれません
答えではなく、コメントではありません。 Cはnamespace
を明示的に定義する方法を提供しません。スコープは可変です。例えば:
int i=10;
struct ex {
int i;
}
void foo() {
int i=0;
}
void bar() {
int i=5;
foo();
printf("my i=%d\n", i);
}
void foobar() {
foo();
bar();
printf("my i=%d\n", i);
}
変数および関数に修飾名を使用できます。
mylib.h
void mylib_init();
void mylib_sayhello();
名前空間との唯一の違いは、using
になれないこと、およびfrom mylib
。
この機能をCに追加したい人は、コンパイラの作者チームとISO団体に圧力をかけるために集まって組織化していないからです。
ANSI Cは、名前空間の前に発明されました。