わさっきhb

大学(教育研究)とか ,親馬鹿とか,和歌山とか,とか,とか.

関数の中で引数の値を書き換えたい?

ところが,プログラム言語と数学は別物であり,関数が1つの値しか返せないとなると大変困ることになる.それを考えると,関数の定義がこのような定義で良いのか分からない.言えることは,引数で値を返すことができないため,C言語ではポインタを多用せざるを得ず,初心者が混乱に陥る場合が少なくない.つまり,C言語のプログラミングを習いはじめた直後に,ポインタを理解しなければならない状況に追い込まれがちである.
(ここが変だよC言語 上, p.100)

上の引用は,「値渡しよりも参照渡しのほうがいいのでは?」という疑問に集約されます.
もちろん現実にはthe fact is that,Cでは必ず値渡しです.
int型などの算術型の引数が,参照渡しになればいいのにというのは,Cのこれまでの資産やノウハウを放棄することになるだけでなく,関数の独立性*1を保てなくなり,とても承服できません.
ポインタを使わずに参照渡しにしたければ,&つきの変数を宣言する*2という方法もあります.ただし言語はCではなくC++となり,コンパイルコマンドや仕様の細部が違うなどの注意が必要です.

配列の受け渡しについて

ここで上の議論から離れて,配列を関数で受け渡しする際はどうかを,検討してみます.
配列を関数で受け渡しする場合でも,配列の先頭アドレスを値として渡しています.関数の中で,仮引数を介して参照先を書き換え,関数を終えると,呼び出し元では,配列の中身が変わったように見えるという仕掛けです.このとき,関数の呼び出しや,関数からの復帰の際に,配列のコピーが起こらず,効率よく処理できます.
配列を配列のように受け渡しするよう(ポインタを隠蔽して),関数を定義することは,たいていの場合,難しくありません.仮引数を配列形式で書くことが認められていますし,配列の要素数は,#defineであらかじめ定義しておけばいいのです.ただしそれが書きやすく,初心者にも熟練者にも読みやすいかどうかは,ケースバイケースです.
配列のようなものに対して,関数内で配列のように受け渡しする,というのは欲張りすぎです.配列のようなものの典型例は,文字列です*3.文字列のいくつかはchar配列に格納されますが,文字列は必ず配列として表現されているとなると間違いです.反例は,コマンドライン引数argvが参照する文字列です.
実引数が文字列のとき,仮引数の配列サイズ(char配列の要素数)を,コンパイル時に求められるとは限りません.
素数が例えば10と決まっているchar配列であっても,そういうふうに上限が決まっていないメモリ領域であっても,文字列(として格納されているデータ)を統一的に扱うために,関数の仮引数を「char *」のポインタ変数として定義し,文字列の先頭アドレスを受け取る,というのは,不便どころか賢明な解法でしょう.