0Pricing
C Academy · レッスン

externとリンケージ

ファイル間でシンボルを共有します。

「externとリンケージ」はCoddyKit上の無料C Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C Academyコースには全4レッスンが含まれています。

リンケージとは

リンケージは、名前を異なるソースファイル間で共有できるかどうかを表します。

外部リンケージを持つ名前は、プログラム全体で同じ実体を参照します。内部リンケージを持つ名前は、それ自身のファイル内だけで使える非公開の名前です。複数ファイルで構成されるプログラムでは、リンケージの理解が重要です。

変数の共有

2つのファイルから1つのグローバルカウンタにアクセスする必要があるとします。単純に両方のファイルで定義してはいけません。そうすると別々の変数が2つ作られ、リンク時にシンボル重複エラーが発生します。

代わりに、1か所でのみ定義し、それ以外の場所ではexternを使って宣言します。

/* config.c */
int g_count = 0;   /* the one definition */

externキーワード

externは、変数がプログラム内の別の場所に存在することをコンパイラに伝えます。ただし、ここではそのための領域を確保しません。

これは純粋な宣言です。リンカーが後で、別のファイルにある1つの定義に解決します。

/* other.c */
extern int g_count;   /* declared, not defined */

void bump(void) {
    g_count++;
}

ヘッダーでの宣言

推奨されるパターンは、extern宣言をヘッダーに置き、対応する定義をちょうど1つのソースファイルに置くことです。

そのヘッダーをインクルードしたファイルからは、共有変数を使えるようになります。

/* config.h */
#ifndef CONFIG_H
#define CONFIG_H
extern int g_count;
#endif

1つの定義と複数の宣言

これはグローバル変数に対するOne Definition Ruleです。変数は複数のファイルでexternを付けて宣言できますが、定義できるのは1つのファイルだけです。

externを付けない1つの定義が記憶領域を確保します。すべてのextern宣言は、その定義を参照するだけです。

/* config.h */ extern int g_count;  /* declaration */
/* config.c */ int g_count = 0;     /* definition  */

関数にも外部リンケージがある

関数もデフォルトでは外部リンケージを持つため、ヘッダーにプロトタイプを記述すれば、他のファイルから呼び出せます。

プロトタイプの前にexternと書くこともできますが、冗長です。別途指定しない限り、関数は外部リンケージになります。

/* both forms mean the same */
int add(int a, int b);
extern int add(int a, int b);

staticによる内部リンケージ

ファイルスコープでstaticキーワードを使うと、その名前は内部リンケージになります。つまり、そのソースファイル内でのみ参照できます。

モジュール内部に限定したいヘルパー関数やグローバル変数に使います。他のファイルからは参照できず、名前が衝突することもありません。

/* parser.c */
static int line_no = 0;   /* private to parser.c */

static void advance(void) {  /* private helper */
    line_no++;
}

externとstaticの違い

この2つのキーワードは、リンケージにおいて正反対の役割を持ちます。

externは外部リンケージを要求し、ファイル間でこの名前を共有します。ファイルスコープのstaticは内部リンケージを強制し、この名前を非公開にします。適切に選ぶことで、モジュールが外部に公開するものを制御できます。

extern int shared_total;   /* visible everywhere */
static int local_cache;    /* only this file */

よくある間違い

初心者は、ときどきヘッダーにint g_count;のような通常の定義を書いてしまいます。

ヘッダーが複数のファイルでインクルードされるため、各ファイルにそれぞれ定義が作られ、リンカーがシンボル重複を報告します。ヘッダーでは必ずexternを付けて宣言し、.cファイルでは1回だけ定義してください。

/* WRONG in a header included twice */
int g_count;          /* multiple definition */
/* RIGHT */
extern int g_count;   /* declaration only */

全体を組み立てる

この3ファイル構成が、状態を共有する標準的な方法です。

ヘッダーで宣言し、1つのソースファイルで定義し、他のファイルではヘッダーをインクルードして使います。リンカーがすべての参照を1つの定義に結び付けます。

/* config.h */ extern int g_count;
/* config.c */ #include "config.h"
               int g_count = 0;
/* main.c   */ #include "config.h"
               /* uses g_count */

初期化に関する注意

初期値を指定するのは、実際の定義だけにしてください。int g_count = 0;のように記述します。

extern宣言では記憶領域を確保しないため、初期化してはいけません。extern int g_count = 0;と書くと定義になり、externを使う目的が失われます。

extern int g_count;       /* ok: declaration */
extern int g_count = 0;   /* becomes a definition */

理解度チェック

externとリンケージについて理解できているか確認しましょう。

まとめ

リンケージによって、ファイルをまたいだ可視性が決まることを学びました。externは別の場所で定義された名前を宣言し、ファイルスコープのstaticは名前を非公開にします。

グローバル変数は、1つの定義と複数のextern宣言によって共有します。次は、これらのファイルをコンパイルしてリンクし、プログラムにします。

よくある質問

「externとリンケージ」レッスンは無料ですか?

はい。「externとリンケージ」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C Academyコースには全4レッスンが含まれています。

「externとリンケージ」で何を学びますか?

ファイル間でシンボルを共有します。 ブラウザで直接実行するハンズオンコードでC Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

C Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのC Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。

「externとリンケージ」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このC Academyレッスンでコードを書いて実行できますか?

はい。すべてのC Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. ヘッダーファイルとソースファイル
  2. インクルードガード
  3. externとリンケージ
  4. 複数ファイルをコンパイルする
← C Academyに戻る