3

C グローバル変数を複数のファイル (コンパイル ユニット) 間で共有する方法を理解しようとしています。ここで素晴らしい質問と回答を読みました。ただし、いくつかのテストを行った後、まだ得られないものがいくつか残っています。

基本的に私の質問は次のとおりです: キーワードなしでヘッダーに宣言されている (ただし定義されていない) 変数がある場合、externその変数をすべてのコンパイル ユニットで使用できるようにするために、さまざまなコンパイル ユニットにそのヘッダーを含めるだけで問題ありませんか? このシナリオでは、1 つ (そして 1 つだけ) のコンパイル ユニットにその変数を初期化 (定義?) するためのコードが含まれていることを意味し、他のコンパイル ユニットがその変数を使用して何かを実行しようとする前に最初に呼び出されます。これがすべて当てはまる場合、この手順は「暗黙の外部」と呼ばれるものですか?

私の質問を例で説明します:

ヘッダー「MyCommonHeader.h」には次が含まれます。

//MyCommonHeader.h
int* i; //pointer to an int

ファイル MyFirstHeader.h には以下が含まれます。

//MyFirstHeader.h
void changeIt(int newValue);

ファイル MyFirstSource.c には以下が含まれます。

//MyFirstSource.c
#include "MyFirstHeader.h"

 void changeIt(int newValue) {
    *i = newValue;
 }

ファイル MySecondSource.c には以下が含まれます。

//MySecondSource.c
#include "MyCommonHeader.h"
#include "MyFirstHeader.h"

void main() {
   i = malloc(sizeof(int));
   changeIt(10);
   *i = 23;
}

上記のコードはどこでも同じ i 変数で動作しますか? externどこかに追加する必要がありますか?

4

4 に答える 4

5
/* file.h */
int* i;

i変数の暫定的な定義です。これは、翻訳単位にその変数の他の (外部) 定義がない場合、一度だけ定義される (に初期化される0) ことを意味します。翻訳単位の他の場所に一致する (外部) 定義が 1 つだけ存在する場合i、その定義が使用され、上記の暫定的な定義が宣言として動作します。

一般的な拡張機能として、コンパイラはこの動作を翻訳単位全体に拡張します。つまり、そのようなコンパイラの場合、そのヘッダー ファイルを必要な数の翻訳単位に安全に含めることができ、i.

iヘッダー ファイルでも明示的に初期化していた場合は異なります。

/* file.h */
int* i = 0;

これは実際の定義 (暫定的ではない) であり、そのヘッダー ファイルを 1 つのコンパイル ユニットにのみ含めることができます。そうしないと、複数定義エラーが発生します。

より良い方法は、.c ファイルで変数を定義externし、ヘッダー ファイルで使用することです。

/* file.h */
extern int* i;

/* file.c */
int* i = 0;

これにより、1 つの定義 (.c ファイル内の定義) しかなく、ヘッダー ファイルが含まれるすべてのコンパイル ユニットがその定義を参照することが明確になります。

于 2013-05-14T12:02:16.157 に答える
1

ヘッダーで変数を宣言し、同じ変数を宣言するソース ファイルがある場合、各コンパイル ユニットはこの変数の異なるインスタンスを持ちます。

1 つのコンパイル ユニットで宣言し、ヘッダーに「extern ...」を追加すると、すべてのコンパイル ユニットが同じグローバル変数にアクセスするようになります。

于 2013-05-14T11:47:50.273 に答える
0
Does the above code operates with the same i variable everywhere?

はい。

Do I need to add externanywhere?

この例では、必要ありません。MyCommonHeader.hは、i が定義されている場所に 1 回だけ含まれるためです。

次の例でexternは、の方が便利です。

//main.c

#include <stdio.h>
int globaldata;
int main()
{
..
}

//Includes.h    
extern int globaldata;


//Feature1.c
#include "Includes.h"

int func()
{
   globaldata++;
}

//Feature2.c
#include "Includes.h"

int func_new()
{
   globaldata = globaldata * 100;
}

globaldatafeature1.c と feature2.c で使用されるグローバル変数です。その変数を定義すると、複数宣言エラーのようにエラーになります。

したがって、このシナリオでは常に extern が使用され、そのヘッダーのみが含まれます。

于 2013-05-14T11:55:31.843 に答える