C の extern キーワード

胡金庫 2023年10月12日
C の extern キーワード

この記事では、C 言語で extern キーワードを使用する方法について複数の方法を示します。

他のファイルで定義された変数を C 言語で宣言するために extern キーワードを使用する

一般的に、C 言語の変数には、外部リンケージ、内部リンケージ、無リンケージの 3 種類のリンケージがあります。ブロックスコープや関数スコープで変数が定義されている場合は、リンクがないとみなされます。ファイルスコープを持つ変数は、内部リンケージと外部リンケージを持つことができます。つまり、グローバル変数が static 修飾子で宣言されている場合、その変数は内部リンクを持ち、その変数が単一のソースファイル(より正確には翻訳単位)で使用できることを意味しています。static 修飾子を持たないグローバル変数は外部リンクを持ち、異なるソースファイルで使用できると考えられます。他のソースファイルで定義されたグローバル変数を使用するには、キーワード extern を使って宣言しなければなりません。

#include <stdio.h>
#include <stdlib.h>

#ifndef COUNT
#define COUNT 10
#endif

extern int counter;

int main(void) {
  printf("counter: ");
  for (int i = 0; i < COUNT; ++i) {
    counter += 1;
    printf("%d, ", counter);
  }
  printf("\b\b \n");

  exit(EXIT_SUCCESS);
}

出力:

counter: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10

通常、extern 修飾された変数は別のファイルのどこかで定義されています。しかし、技術的には、以下の例のように、同じファイル内で extern キーワードを使用してグローバル変数を宣言することができます。コンパイラは自動的に同じファイルスコープ内のどこにいても変数名が見えるようにするので、このタイプの宣言は基本的に冗長です。

#include <stdio.h>
#include <stdlib.h>

#ifndef COUNT
#define COUNT 10
#endif

int counter2 = 0;

int main(void) {
  extern int counter2;  // redundant
  counter2 += 10;
  printf("%d\n", counter2);

  exit(EXIT_SUCCESS);
}

ただし、extern 宣言された変数は初期化すべきではないことに注意してください。同じ変数を const 修飾子を付けずに別のソースファイルで宣言しても、警告は出ずにコンパイルされ、オブジェクトの const 性が削除されます。したがって、ユーザが読み取り専用の文字列 tmp を変更しようとした場合、コンパイラはエラーをスローしませんが、プログラムはセグメンテーションフォールトを起こします。

#include <stdio.h>
#include <stdlib.h>

#ifndef COUNT
#define COUNT 10
#endif

extern int counter;
// extern int counter = 3; // erroreous
extern char *tmp;  // erroreous

int counter2 = 0;

int main(void) {
  printf("counter: ");
  for (int i = 0; i < COUNT; ++i) {
    counter += 1;
    printf("%d, ", counter);
  }
  printf("\b\b \n");

  tmp[0] = 'S';  // segmentation fault
  printf("%s", tmp);

  exit(EXIT_SUCCESS);
}
著者: 胡金庫
胡金庫 avatar 胡金庫 avatar

DelftStack.comの創設者です。Jinku はロボティクスと自動車産業で8年以上働いています。自動テスト、リモートサーバーからのデータ収集、耐久テストからのレポート作成が必要となったとき、彼はコーディングスキルを磨きました。彼は電気/電子工学のバックグラウンドを持っていますが、組み込みエレクトロニクス、組み込みプログラミング、フロントエンド/バックエンドプログラミングへの関心を広げています。

LinkedIn Facebook