C言語の解説には歴史的経緯からか、あまり良くない記述が散見されます。
その中でも特に良くないのが「ポインタ渡し」です。
C言語には「値渡し」しかない
プログラミング言語において、引数の渡し方は2種類あります。
-
値渡し
変数の値をコピーして渡します。
関数内で値が編集されても元の変数の値に変更はありません。 -
参照渡し
変数を指し示す参照だけを渡し、変数として振舞わせます。
関数内で値が編集されると元の変数の値が変更されます。
皆さんがC言語を書いている時に、「変数として振舞う参照」とやらを見たことはないと思います。
「ポインタ渡し」なんてものはない
「でも入門書で『ポインタ渡し』っていうの見たよ! 値渡しでもないし、参照渡しでもないならどうなるの!?」と思うかもしれません。
簡単です。
「ポインタ渡し」なんてものは、C言語の仕様には存在しません。
そもそも、ないんです。
「ポインタ渡し」の正体
まず、ポインタというものについて思い出してみましょう1。
ポインタは変数の場所を指し示す値でしたよね。
そして、ポインタ p に * をつける(*p)ことで元の変数を間接参照できるんでした。
ここで、「ポインタ渡し」だと思っていたものを見てみましょう。
まず引数にポインタ p を渡して、関数内では引数として受け取ったポインタ p に、 * をつける(*p)ことで、元の変数を間接参照していました。
……ちょっと待て。ただ、ポインタを間接参照しているだけでは?
だとしたら。渡したのはポインタで、受け取ったのも同じポインタです。
これって、値渡しと何が違うんでしょうか。
ポインタの値渡し
そうです。
今まで「ポインタ渡し」と呼んできたものは「ポインタの値渡し」。
つまりはただ、変数の場所を指し示す値(ポインタ)をコピーして渡しているだけだったのです。
なので、最初に「C言語には『値渡し』しかない」と書いたわけですね。
整数値を「値渡し」するか、ポインタを「値渡し」するか、文字を「値渡し」するか。
C言語は常に「値渡し」しかしないのです。
あとがき
個人的には、初心者に「ポインタ渡し」という用語を使って説明するのは、やめた方がいいと思っています。
理由は簡単で、「ポインタを値渡しすれば元の変数を間接参照して読み書きできる」ということがわからないとしたら、それはポインタ自体を理解していないということに他ならず、逆にわかるのであれば、「ポインタの値渡し」と言うことで一発で過不足なく理解できるからです。
もしそれがわからないのであれば、ポインタについてきちんと理解を深めるべきであって、「ポインタ渡し」という新しい語を使ってごまかすべきではありません。
なぜなら、C言語の本質はメモリを操作すること2であり、その過程でポインタの理解と利用は不可欠であるためです。
わかっている人同士の間であれば、「ポインタの値渡し」なんてまどろっこしい言い方は面倒ですし、「ポインタ渡し」と言ってもよいと思います。
便宜上そういった用語が使われる、それ自体は悪いことではありません。
しかし、初心者に「ポインタ渡し」という用語を使うと、ポインタについて学ぶ機会を奪う上に、C言語の引数の仕組みについて間違った認識を植え付けてしまいます。
私はこれでだいぶ無駄な時間を過ごす羽目になりました。
もし、今後C言語を誰かに教える機会があるかもしれない、そういった人が読んでくれているなら、なるべく「ポインタ渡し」という用語を避けてほしいな、と思います。
-
ポインタ自体がよくわからないという方には、先に私が前に書いた「ポインタが怖くなくなる!C言語メモリ操作の基本概念」を読むことをおすすめします。 ↩
-
それこそ「ポインタが怖くなくなる!C言語メモリ操作の基本概念」の冒頭で書いたことそのままですが…… ↩