名前空間を持つことは、ほとんどの言語にとって簡単なことのように思えます。しかし、私が知る限り、ANSI C はそれをサポートしていません。なぜだめですか?将来の標準に含める予定はありますか?
10 に答える
完全を期すために、名前空間から得られる「利点」を 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 には名前空間があります。1 つは構造タグ用で、もう 1 つはその他のタイプ用です。次の定義を検討してください。
struct foo
{
int a;
};
typedef struct bar
{
int a;
} foo;
最初のものはタグfoo を持ち、後者は typedef で型 foo になります。それでも名前の競合は発生しません。これは、構造タグと型 (組み込み型と型定義型) が別々の名前空間に存在するためです。
C で許可されていないのは、意志によって新しい名前空間を作成することです。C は、これが言語で重要であると見なされる前に標準化されました。名前空間を追加すると、下位互換性も脅かされます。これは、名前のマングリングが正しく機能する必要があるためです。これは、哲学ではなく技術的な理由によるものだと思います。
編集: JeremyP は幸いなことに私を修正し、私が見逃した名前空間について言及しました。ラベルと構造体/共用体メンバーの名前空間もあります。
C には名前空間があります。構文はnamespace_name
. のようにネストすることもできますgeneral_specific_name
。また、毎回名前空間名を書き出すことなく名前にアクセスできるようにしたい場合は、関連するプリプロセッサ マクロをヘッダー ファイルに含めます。
#define myfunction mylib_myfunction
これは、名前のマングリングや、特定の言語が名前空間を提供するためにコミットしている他の残虐行為よりもはるかにクリーンです。
歴史的に、C コンパイラは名前をマングルしません (Windows ではマングルしますが、cdecl
呼び出し規約のマングルはアンダースコア プレフィックスを追加するだけです)。
extern "C"
これにより、他の言語 (アセンブラーを含む) から C ライブラリーを簡単に使用できるようになり、C++ API のラッパーをよく目にする理由の 1 つになっています。
ただの歴史的理由。当時、名前空間のようなものを持つことは誰も考えていませんでした。また、彼らは本当に言語をシンプルにしようとしていました。彼らは将来それを持っているかもしれません
ANSI C は名前空間が発明される前に発明されました。
答えではありませんが、コメントではありません。namespace
C は、明示的に定義する方法を提供しません。可変範囲があります。例えば:
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
です。