1

私は最近、「extern」キーワードの使用が強く推奨されていることに気付き始めました。したがって、ヘッダー ファイルを使用する現在の (extern なしの) 方法に何か問題があるのではないかと考え始めました。

main.c:

#include "main.h"
#include "function.h"

int main(void){
    globalvariable = 0;

    testfunction();
    return 0;
}

main.h:

#ifndef MAIN_H_
#define MAIN_H_

int globalvariable;

#endif /* MAIN_H_ */

関数.c:

#include "main.h"
#include "function.h"

void testfunction(){
    globalvariable++;
    return;
}

関数.h:

#ifndef FUNCTION_H_
#define FUNCTION_H_

void testfunction(void);

#endif /* FUNCTION_H_ */

したがって、 globalvariableへのアクセスが必要な新しいソース ファイルはすべて、main.h をインクルードするだけで済みます。

このメソッドの明らかな欠点の 1 つは配列です。{element0, element1, ...} フォーマットを使用して、配列が宣言された後に値を配列に割り当てることはできません。

ところで、globalvariableに初期値ゼロを与える場合、その時点で定義しているのでしょうか? または、メモリが以前に割り当てられていますか?

また、私が使用している方法の正式な用語はありますか?

4

5 に答える 5

2

これに伴う問題は、プログラムをリンクしようとすると、複数の定義が原因でリンクエラーが発生する可能性があることです。ここでは、実装で定義された動作に依存しています。実装は、重複する定義をすべて単一のオブジェクトを参照しているものとして扱うことができますが、必須ではありません。

于 2012-04-09T20:25:59.477 に答える
2
extern int globalvariable;

宣言です

int globalvariable;

は宣言であり、暫定的な定義でもあります。

Cでは、同じ変数に複数の定義を含めることは違法です。これは、複数の変換ユニットに含まれるヘッダーファイルで後者を使用する場合に発生します。

ただし、Unixシステムは歴史的にこの使用法を許可しているため、ほとんどのコンパイラはコードが無効なCであってもコードを受け入れます。

于 2012-04-09T20:26:13.160 に答える
2

あなたが使用している方法について私が知っている唯一の公式用語は、「実装依存の動作」です。異なるコンパイラ (または同じコンパイラの異なるバージョン) でビルドを開始すると、その方法であらゆる種類の問題に遭遇します。リンカー エラーをスローするものもあれば、それを受け入れるものもあります (ただし、正確にどのように解釈されるかは保証されません)。コンパイラが予測可能な方法で解釈する、より標準的なアプローチを採用することを強くお勧めします。

変数の定義は、.c ファイルにある必要があります。別の .c ファイルからその変数にアクセスする場合は、ヘッダーにextern 宣言を追加します。この手法は標準 C であり、準拠するコンパイラで予測どおりに解釈されます。

割り当てに関する質問に答えるために、プログラムの実行が開始される前に、すべてのグローバルのメモリが割り当てられます。グローバル変数は、決して実行されないコードのサブセクションでのみ使用されている場合でも、スペースを占有します。あなたのglobalvariable = 0;行は実際には変数に初期値を与えていません。C コンパイラは、プログラムのロード時に、初期化されていないすべてのグローバル変数が自動的にゼロに初期化されるようにします。あなたのコードは技術的に変数の値を再割り当てしています。グローバルが特定の値に初期化されることを確認したい場合は、 のような定義に初期化子を追加しますint globalvariable = 42;

于 2012-04-09T21:17:17.780 に答える
2

コードの欠点は、おそらくリンカー エラーが発生することです。1


1.「おそらく」は、さまざまなツールチェーン全体でコードを構築するという概念に基づいています。

于 2012-04-09T20:24:17.810 に答える
0

ANSI C標準は言う

オブジェクトの識別子の宣言にファイル スコープがあり、ストレージ クラス指定子がない場合、そのリンケージは外部です。

于 2014-07-20T13:25:13.347 に答える