extern指定子 | とらのブログ

とらのブログ

ジャグリングが趣味のプログラマー(?)が綴る適当な日記

毎度ありがとうございます。とらです。
今回は

(カタカタカタカタ)
えくすッターン

のお話。
正直ッターンが言いたかっただけです。
はい。

えくすターン!ドロー!

とかも考えましたが、分かりにくいのでやめました。
まあ、結局書きましたが。

externは、関数や変数の実体がここではないどこかで定義されていますよー、
というのをコンパイラに教える役割を持っています。
ここで言う変数とは、グローバル変数のことを指します。

コンパイラは、ソースファイル(*.c)を一つずつ機械語に翻訳し、オブジェクトファイル(*.o)を生成します。
その際、他のソースファイルを参照することはありません。
つまり、ソースファイル単体で自己完結している必要があります。
簡潔に言うと、他のソースファイルで定義された関数や変数を利用できないということです。
「なんじゃこりゃあ!」と言ってエラーをだします。

これは困った。
このままでは1つのファイルで何万行というトンでもコードが出来てしまう。。。

そこで登場するのがexternです。
最初に書いた通り、これは関数・変数の実体を他のファイルで定義していることをコンパイラに教えます。
するとコンパイラは「よくわからんけど、その内わかるんだな。」と保留にし、オブジェクトを生成してくれます。

オブジェクト生成後、コンパイラははリンクと呼ばれる作業に移ります。
ここで他のオブジェクトとの結びつけをし、保留にしていた関数・変数が見える(実体がある)状態になります。
この時、どのオブジェクトにも定義されていなかった場合、リンクエラーとなります。

プログラムを書くとき、よくヘッダファイルで関数の宣言をしますが
これは暗黙的にextern宣言として扱われているそうです(要ソース)。

そうそう、ヘッダにexternを入れずグローバル変数を定義してしまうことがあるそうですが、
このときの扱いはどうなるのでしょうか?

多重定義エラーを出すコンパイラにしか出会ったことがないのでわかりませぬ。

externはあまりCファイルで乱用しない方が良いようです。
どこでだれが参照しているのかわからなくなる可能性があるので。

ヘッダで定義してインクルードしてあげるのが適切かと思います。

追記
配列をexternで宣言する場合、要素数は書かなくてもOKと思っていました。
が、これは一次元配列に限るようです。
2次元配列でやったところ多重定義エラーを出されました(´・ω・`)

○ extern int array[]
× extern int array[][]
× extern int array[num][]
× extern int array[][num]


以上、誰得なexternのお話でした。