はじめての C
C programming note*1
関数 do_one() の 引数の 説明は、外部変数の 解説のところで でてきます。
「名前の 適用範囲 scope」というものを 説明しよう。 main() 関数内で
FILE *fp;
と 宣言されている fp という変数は 他の 関数の中では 使えない。 これは main() の 関数定義の ブロック ( { } で 囲まれた範囲 ) 内で 宣言されているので、その範囲内だけで 適用する 宣言と なっているわけだ。それに対して、関数の外側で 宣言されているものを 外部宣言 external declaration と 呼ぶ。
変数を 外部宣言すると、その変数は 1つの 関数内だけでなく、ファイル中で その宣言以降に 現れる すべての関数で 適用する 名前となり、どの関数の中でも 参照できるようになる。 外部宣言された 変数を 外部変数 external variable という。(p106-107)
注意すること として、
変数を やたらと 外部宣言してはいけない。 不用意な 変更や 知らないうちに 参照しているような 事態を 避けるために、変数は なるべく 必要な 関数内だけで「見える」ように 宣言すべきだ。
(ある外部変数が) へたに「どの関数でも (関数の外でも) 適用する名前」に なっていると、1つの 変数についての 変更を 行なうたびに、そのファイルを すべて読んで その変数の 使われ方を チェックし、影響が ないかどうかを 調べなければいけない。 それは いかにも 効率が 悪いし、プログラムの 信頼性も 落ちる。(p107-108)
で、do_one() では なぜ 引数渡しを 行なうのか、というと、
ある変数を 複数の関数で 使用する場合、その変数を 外部宣言する 方法以外に、「引数で渡す」という 方法も 考えられる。 do_one() における 引数 fp などが そうだ。 この 2つの方法のうち どちらが 適しているかは、場合による。
do_one() の場合、呼び出す側の 関数で 値の設定や 変更をするが、渡された側の 関数では 値の参照しか していないので、この方法が 使える。
呼び出された側でも 値の変更の 必要が あるなら、引数で渡す 方法は 使えない。 C では、呼び出された 関数内で 仮引数を 変更しても、呼び出し側で 実引数として 与えられた 変数には 影響を 与えないからである。(p108)
ついでに、cant() 関数の 引数についても、
つまり、C では 呼ばれた関数が 呼び出した関数の 変数を 直接 改変することは できないからだ。 値による 呼び出し call by value とも いう。
呼び出された 関数側で、呼び出した 関数側の 変数の内容を 変更したい場合は、引数には 変数のアドレス (変数へのポインタ) を 渡す必要がある。 もちろん、呼ばれる 関数側でも その引数が ポインタ型であると 宣言していなければならないし、そのポインタを 使って 間接的に 値を 参照するわけだ。
ただし、配列の場合は 事情が 異なる。 配列の名前を 関数の 引数として 使うと、その場合は その配列の 先頭アドレスが 渡される。 つまり、呼ばれた 関数側では ポインタとして うけとるわけだ。
このことが 理解できれば cant() 関数の 引数についても 理解できることだろう。(p109-110)
それで cant() の 引数が *argv と なってるのか ...
*1:「作ってわかる Cプログラミング」