「14歳からはじめる・・・」ですね。私も読むのに時間がかかりました。非常に勉強になって面白い本だと思います。
externの使い方なのですが... 難しいですよね。コレ、重要なんですけど詳しく解説している本はあまり多くないです。実は今読んでいる本(「14歳から・・・」)の5章にこれの解説が多少書いてあります。他の解説書とは違う切り口なのでためになります。
hideさんの解説もためになりますし、K&Rとかロベールとか良解説もたくさんありますが、ぶっちゃけすぐには理解できないと思います。英語と同じように、aってなんだ、theってなんだ、atってなんだーと問答するのではなく、解説とサンプルコードを分からなくてもいいからたくさん読んで、少しづつ理解するようにします。そうすれば1,2年後くらいにはわかります(私なんて10年かかりましたよ)。
.cppファイルと.hファイルについて、少し説明してみたいと思います。
C/C++の実行ファイル作成にはコンパイルとリンクの2工程があります。基本的に、.cppファイルは中間ファイルと対応づきます。
a.cpp b.cpp c.cpp --(コンパイル)--> a.obj b.obj c.obj --(リンク)--> out.exe
これらの中間ファイルが、どういうものかと言いますと、以下のような感じです(これはg++の結果なので、こんなイメージというのをつかんでください)
a.cpp
コード:
extern sqrt(int, int);
extern int add(int a, int b) { return a+b; }
extern float distance(float x, float y) { return sqrt(x*x, y*y); }
↓
ex1.obj(バイナリファイル)の逆アセンブル結果(抜粋)
コード:
RELOCATION RECORDS FOR [.text]:
OFFSET TYPE VALUE
0000000000000045 R_X86_64_PC32 _Z4sqrtii
0000000000000000 <_Z3addii>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: 89 4d 10 mov %ecx,0x10(%rbp)
7: 89 55 18 mov %edx,0x18(%rbp)
a: 8b 55 10 mov 0x10(%rbp),%edx
d: 8b 45 18 mov 0x18(%rbp),%eax
10: 01 d0 add %edx,%eax
12: 5d pop %rbp
13: c3 retq
0000000000000014 <_Z8distanceff>:
14: 55 push %rbp
15: 48 89 e5 mov %rsp,%rbp
18: 48 83 ec 20 sub $0x20,%rsp
1c: f3 0f 11 45 10 movss %xmm0,0x10(%rbp)
21: f3 0f 11 4d 18 movss %xmm1,0x18(%rbp)
26: f3 0f 10 45 18 movss 0x18(%rbp),%xmm0
2b: f3 0f 59 45 18 mulss 0x18(%rbp),%xmm0
30: f3 0f 2c d0 cvttss2si %xmm0,%edx
34: f3 0f 10 45 10 movss 0x10(%rbp),%xmm0
39: f3 0f 59 45 10 mulss 0x10(%rbp),%xmm0
3e: f3 0f 2c c0 cvttss2si %xmm0,%eax
42: 89 c1 mov %eax,%ecx
44: e8 00 00 00 00 callq 49 <_Z8distanceff+0x35>
49: 66 0f ef c0 pxor %xmm0,%xmm0
4d: f3 0f 2a c0 cvtsi2ss %eax,%xmm0
51: 48 83 c4 20 add $0x20,%rsp
55: 5d pop %rbp
56: c3 retq
57: 90 nop
58: 90 nop
59: 90 nop
5a: 90 nop
5b: 90 nop
5c: 90 nop
5d: 90 nop
5e: 90 nop
5f: 90 nop
関数sqrtはexternしていますが、定義はしていないので、他の.cppファイルの関数としてコンパイラに認識されます。すると、リロケーションテーブルという所にsqrtに対応したシンボルを用意します。さらに、
コード:
44: e8 00 00 00 00 callq 49 <_Z8distanceff+0x35>
この行の00 00 00 00はsqrtが分からないので仮置きしているものですが、アドレス(コードの場所)は
コード:
0000000000000045 R_X86_64_PC32 _Z4sqrtii
の45に対応していて、リンカは他のオブジェクトのsqrtシンボルと結びつけるという作業を行います。
addとdistanceはexternしていますが、定義をしているので、関数がアセンブラコードに変換されて、add, distanceに対応したシンボルがそれらのアセンブラコードの先頭に割り付けられます。
.hファイルは、このようなオブジェクトファイルを作ることではなく、複数の.cppファイルにマクロ、型宣言、関数宣言を配ることを目的としています。
このような視点でソースコードを見ていくとわかりやすいのではないかと思います。