5

次の例を検討してください。

static int a;
extern int a; //OK -- what linkage does the a have now?

static int a;
int a; //ERROR

extern int a;
static int a; //ERROR

int a;
static int a; //ERROR

extern int a;
int a; //OK as expected

int a;
extern int a; //OK as expected

最初の例では問題がなかったのに、2番目の例では問題がなかったのはなぜですか。

ファイルスコープ変数(グローバルスコープ)に関する限り、これらには外部リンケージがあり、キーワードが指定されていない場合は静的期間があります。

ありがとうございました

関数のAFAIK、リンケージ、および保存期間は少し異なります。

編集:gcc 4.5.2 -Wall -pedantic --std=c99を使用してコンパイルしてみました

詳細:http ://c-faq.com/decl/static.jd.html 1番目の例もそこで機能しますが、2番目の例は機能しないことがわかります。しかし、何がそんなに違うのかわかりません。

4

2 に答える 2

6

最初の質問に対する答えは、C標準の§6.2.2にあります。

4その識別子の前の宣言が表示されるスコープでストレージクラス指定子を使用extern して宣言された識別子の場合、前の宣言が内部または外部のリンケージを指定している場合、後の宣言での識別子のリンケージはリンケージと同じです。事前の宣言で指定されています。以前の宣言が表示されていない場合、または以前の宣言でリンクが指定されていない場合、識別子には外部リンクがあります。

したがって、のリンクaは内部です。

2番目の質問では、直後の段落の2番目の文が適切です。

5関数の識別子の宣言にストレージクラス指定子がない場合、そのリンケージは、ストレージクラス指定子で宣言された場合とまったく同じように決定されますextern。オブジェクトの識別子の宣言にファイルスコープがあり、ストレージクラス指定子がない場合、そのリンケージは外部にあります。

aは関数ではなくオブジェクトであるためint a;、ストレージクラス指定子のない宣言はa外部リンクを提供します。同じセクションには、次のように書かれています。

7変換ユニット内で、内部リンケージと外部リンケージの両方で同じ識別子が表示される場合、動作は定義されていません。

2番目の例でaは、内部リンケージと外部リンケージの両方で表示されるため、この段落がトリガーされます。未定義動作の1つの(特に役立つ)兆候は、コンパイラーが生成しているエラーです。

すべての例は、次のルールで理解できます。

  1. int a;a常に外部リンケージで宣言します。
  2. static int a;a常に内部リンケージで宣言します。
  3. extern int a;aすでに持っていたリンケージ、または持っていない場合は外部リンケージで宣言します。
  4. リンケージが異なる同じスコープ内の2つの宣言はa、未定義の動作を示します。
于 2011-08-30T06:02:31.050 に答える
0

「;」ではなく「{」を忘れた場合も同じエラーが発生しました。宣言の終わりに。

例:

extern void *HASHMP_get(struct HASHMP_wf_s *hmwf_ptr, Uint8 *key);
extern void *HASHMP_remove(struct HASHMP_wf_s *hmwf_ptr, Uint8 *key) {
extern Uint16 HASHMP_clear(struct HASHMP_wf_s *hmwf_ptr);
于 2019-06-27T11:00:04.510 に答える