今回は、C++での「extern」について解説していきます。
複数のファイルでグローバル変数を共有したいとき、「どうやって他のファイルから変数を使えばいいの?」と疑問に思ったことはありませんか?
この記事を読み終えると、あなたはexternの使い方をマスターできると思いますので、ぜひ最後まで読んでいただけると嬉しいです。
externとは?
externとは、
・「この変数は別のファイルで定義されていますよ」
とコンパイラに伝えるための宣言
です。
C++では、複数のソースファイルで同じグローバル変数を使いたい場合、extern宣言が必要になります。
通常、変数は「宣言」と「定義」が同時に行われますが、externを使うことで「宣言だけ」を行うことができるのです。
なぜexternが必要なの?
コンパイルはファイル単位で行われます。
そのため、あるファイルで定義したグローバル変数を別のファイルで使おうとすると、コンパイラは「そんな変数は知らない」とエラーを出してしまいます。
例えば、こんなコードを書いたとします。
▼main.cpp
#include <iostream>
int g_count = 0; // グローバル変数を定義
void sub();
int main() {
sub();
return 0;
}▼sub.cpp
#include <iostream>
void sub() {
std::cout << "count = " << g_count; // エラー!
}このコードはコンパイルエラーになります。
なぜなら、sub.cppをコンパイルする際に、コンパイラがg_countという変数を知らないからです。
そこで、extern宣言の出番です。
externの使い方
extern宣言は次のように書きます。
extern データ型 変数名;先ほどのコードを修正してみましょう。
▼sub.cpp
#include <iostream>
extern int g_count; // 外部で定義された変数を宣言
void sub() {
std::cout << "count = " << g_count << std::endl; // これでOK!
}この一行を追加するだけで、コンパイラに「g_countはどこか別のファイルで定義されているよ」と伝えることができます。
ヘッダファイルでexternを使う
実際の開発では、ヘッダファイルにextern宣言をまとめるのが一般的です。
▼main.h
#ifndef MAIN_H
#define MAIN_H
extern int g_count; // ヘッダでextern宣言
#endif▼main.cpp
#include <iostream>
#include "main.h"
int g_count = 0; // 変数の定義と初期化
void sub();
int main() {
g_count++;
sub();
return 0;
}▼sub.cpp
#include <iostream>
#include "main.h" // ヘッダをインクルードするだけ
void sub() {
std::cout << "count = " << g_count << std::endl;
}こうすることで、main.hをインクルードするだけでどのファイルからでもg_countを使えるようになります。
宣言と定義の違い
ここで重要なポイントが「宣言」と「定義」の違いです。
- 宣言:変数の存在をコンパイラに知らせるだけ(何度書いてもOK)
- 定義:メモリ領域を確保する(プログラム全体で1回だけ)
通常、int g_count = 0;と書くと、宣言と定義が同時に行われます。
しかし、externを付けると「宣言だけ」になるため、複数のファイルで書いてもエラーになりません。
extern使用時の注意点
1. 定義は必ず1回だけ
extern宣言だけを書いて、どこにも定義がないとリンクエラーになります。
必ずどこか1つのファイルで定義してください。
2. 初期化はできない
extern宣言と同時に初期化することはできません。
extern int g_count = 0; // これはNG!初期化は定義を行うファイルで行います。
3. グローバル変数の乱用は避ける
externを使えば便利ですが、グローバル変数を多用すると、どこで値が変わったのか追いにくくなります。
本当に必要な場合だけ使うようにしましょう。
配列でのexternの使い方
配列のグローバル変数にもexternを使うことができます。
▼main.h
extern int numbers[]; // 要素数は省略可能▼main.cpp
int numbers[] = {1, 2, 3, 4, 5}; // 配列の定義ただし、extern宣言時に要素数を書かないと、sizeofで配列のサイズを取得できません。
サイズが必要な場合は、次のように書きます。
▼main.h
constexpr int ARRAY_SIZE = 5;
extern int numbers[ARRAY_SIZE];関数にはexternは不要
関数のプロトタイプ宣言には、externを付ける必要はありません。
void func(); // これだけでOK(externは不要)関数の宣言は「定義を伴わない」ことが明確なため、externを付けなくても宣言だけと見なされます。
まとめ
extern宣言は、複数ファイルでグローバル変数を共有するための仕組みです。
- 変数の定義は1つのファイルで行う
- 他のファイルではextern宣言で使えるようにする
- ヘッダファイルにextern宣言をまとめるのが一般的
これでexternの使い方はバッチリですね!
複数ファイルで開発する際に、ぜひ活用してみてください。
ここまで読んでくださり、ありがとうございました。
この記事が皆様の学習に役立てば幸いです。


