3

(私は C について話していますが、C++ のクラス テンプレートにも当てはまります)

ヘッダーファイルには、定義ではなく、すべての宣言を入れるのが習慣です。ただし、通常、構造定義やクラス テンプレートもヘッダー ファイルに配置しますが、その理由を実際に理解することはありません。これらは定義でもあるため、これは実際には意味がありません-1つの定義ルール。(はい、構造定義とクラス テンプレートによってストレージが設定されることはありませんが、定義であることを意味する以下の「再定義」エラーが引き続き発生します)。

例) 同じファイル内で同じタグを持つ複数の構造体を定義すると再定義エラーが発生しますが、複数のソース ファイルで同じタグを持つ複数の構造体を定義してもエラーは発生しません (クラスでも同じことが起こります)。

意味のある唯一のことは、構造定義とクラス テンプレートに内部リンケージ (デフォルトの外部リンケージとは対照的) があることですが、K&R またはリファレンス マニュアルでそれに関する参照を見つけることができません。実際、構造はリンケージでも言及されていません。

ANSI標準がこの現象を指摘している正確な参照を知りたいです。(IMO、これは ANSI 標準のどこかで言及されなければならないかなりあいまいなものです)。


編集 構造定義をヘッダーファイルに入れることができる理由を尋ねているわけではありません。

構造体定義をヘッダー ファイルに配置しても、変数定義をヘッダー ファイルに配置した場合 (およびそれを複数のソース ファイルにインクルードした場合) のように、再定義エラーが発生しない理由を尋ねています。

例) test1.c: int a = 3; test2.c: int a = 4; 再定義によりコンパイルエラーとなります。でも、

test1.c: struct test { int a }; test2.c: struct test { int b }; コンパイルエラーは発生しません。私が思いつく唯一の理由は、構造定義に内部リンケージがあるか、リンケージがまったくないことです。

4

5 に答える 5

4

C では、オブジェクトと関数のみがリンケージを持ちます。structC では C++ のように関数や " " メンバー オブジェクトが含まれない場合があるためstatic、ここでの質問はあまり意味がありません。

C++ のメンバー関数は、定義されておらず、内部でのみ宣言されている限りstruct問題ありません。それらも定義されている場合、それらはinlineです。の概念は、C++ がそのケースを捉えるために考案されたものです。つまり、複数のコンパイル ユニットでヘッダー ファイルを介して共有できるinline関数定義です。そのコンセプトを取り入れたC99(少し改変)。

staticメンバー オブジェクトは実際、より多くの問題を引き起こします。これらの人をインスタンス化する方法に関する構文は、特にtemplate classes またはstructs の場合、非常にあいまいです。それについて知りたい場合は、具体的に C++ でタグ付けされたものを要求する必要があります。

于 2011-08-14T21:44:44.597 に答える
2

ヘッダー ファイルはモジュールへのインターフェイスを提供するため、構造体はヘッダー ファイルで定義されます。インターフェースで構造が定義されると、インターフェースのユーザーは次のことが可能になります。

  • 構造体のメンバーを参照する
  • 構造体の大きさを知っている - そうしないと、構造体にメモリを割り当てることができませんでした

リンケージはそれとは何の関係もありません - 関数のみがリンクされ、データ構造はリンクされません。

ヘッダー ファイルで構造体を宣言できることに注意してください。これは、構造体の内部 (不透明なデータ構造体) を隠したい場合に便利です。インターフェイスのユーザーは、構造体へのポインターを持ち、それらを一種の Cookie として使用できますが、そのような構造体を自分で割り当てたり、その中を「見る」ことはできません。

ヘッダー ファイルで構造体を定義するときに再定義エラーが発生しないのは、単純にヘッダー ガードが原因です。ヘッダーは通常、次のようになります。

#ifdef MYHEADER_H
#define MYHEADER_H

struct a { int x; }
void f(void);
/* and so on */

#endif

そのため、ヘッダー ファイルをインクルードする場合、通常は 1 回だけインクルードされるため、構造は翻訳ファイルごとに 1 回だけ定義されます。構造定義にはリンケージがないため、リンカは構造定義とは関係ありません。

于 2011-08-14T21:28:32.740 に答える
1

構造体行は単なる定義です。定義はソースファイルの外部には表示されません。
参考:どちらのソースファイルも何もエクスポートしません。

これをテストするには:

$ cat test1.c
struct test { char a; };
$ gcc -o test1.o -c test1.c
$ nm 
$ echo "struct test foo; " >> test1.c
$ gcc -o test1.o -c test1.c
$ nm
0000000000000001 C _foo
于 2011-08-14T21:56:14.707 に答える
0

ここで少し混乱していると思います。ヘッダーファイルには好きなものを入れることができます。

それらに入れる通常のものは、列挙型、typedef、構造体、および関数プロトタイプの宣言であるため、実際の関数または実際のメモリを知らなくてもさまざまな C ファイルをコンパイルできます (構造体は基本的に、メモリがどのように配置されるかの定義です)。

于 2011-08-14T21:32:10.353 に答える