前節では、変数のアドレスを表示する方法について説明しました。
このとき、変数名の前に&をつけて表示していましたが、
この書き方は、第6章でscanf関数を使う時にも使いました。
つまり、&付き変数は、アドレスを表示する時だけに使われるのではなくて、
様々な所で使われている書き方なのです。
この&付き変数の正体は、非常に単純です。
実は、&は変数のアドレスを求める演算子なのです。
+や×などと同じように、なんらかの計算を行うための記号なのです。
どんな変数でも、&演算子を使うと、変数のアドレスを求めることが出来ます。
言い換えると、&演算子を使うと、その変数のメモリ上の番号を知ることが出来ます。
前項では、&演算子を使うと、変数のアドレスを知ることが出来ると説明しました。
しかし、一体何のために、変数のアドレスを知る必要があるのでしょうか。
実は、これにはC言語の関数の仕組みが関係しているのです。
第12章では、自作関数と変数のスコープについて説明しました。
ここでは、引数という仕組みで、関数に数値を渡すことが出来ると説明しました。
しかし、この引数で渡すことが出来るのは、あくまでも数値です。
関数を呼び出す時に変数を指定した場合には、
変数に記憶されている値が、呼び出された関数の実引数にコピーされます。
つまり、引数で関数に渡されるデータは、全て数値であるということです。
この様に、引数で数値を渡す方式を、値渡しと呼ぶことがあります。
ここで重要なのは、変数を実引数に指定しても、渡されるのは中身の数値である点です。
[ 値渡し ]
関数に単なる数値として情報を渡す方法。
通常はこれで問題ありませんが、もし、変数の中身を直接変更したい場合には困ります。
何故なら、関数に渡されたのは変数の中身のコピーに過ぎないので、
そのコピーをいくら変更しても、呼び出し側の変数には何の影響もありません。
そこで、&演算子を使ってアドレスを求めて、そのアドレスの数値を渡します。
そうすれば、関数に呼び出し側の変数のアドレス、すなわちメモリ上の番号がわかり、
その番号のメモリを書き換えてやれば、呼び出し側の変数を書き換えられます。
つまり、これが変数のアドレスを知る必要がある理由です。
[ 参照渡し ]
値渡しに対して、参照渡しという機能が存在する言語もあります。
これは、アドレスを渡す処理を言語の機能で自動的に行うことです。
C言語では、あくまでも値渡ししか出来ないのですが、
アドレスを渡すことを慣習的に参照渡しと呼ぶことがあります。
前項で説明したことから考えれば、scanf関数で&をつける理由がわかると思います。
scanf関数は、キーボードからの入力を行い、変数に記憶する関数です。
しかし、前項で説明した通り、C言語では値渡ししか出来ません。
つまり、関数には変数に記憶された値のコピーしか渡すことが出来ません。
これでは、変数に新たな値を記憶することが出来なくなってしまいます。
その場合、前項で説明したように、変数のアドレスを数値として渡してやれば、
関数の側で、そのアドレスにデータを記憶することが出来るわけです。
これが、scanf関数で変数に&をつける理由です。
しかし、疑問なのは、文字列を入力する時は、配列名の前に&をつけなかったことです。
これは、前節で説明したように、配列名は配列の最初の要素のアドレスを表しています。
従って、配列名を渡せば、配列の場所がわかるため、&は不要です。
つまり、ある意味配列名でなくても、配列のアドレスさえ指定すれば良いのです。
例えば、次のようにすれば、配列名でなくても入力が出来ます。
このプログラムの実行結果は、次の通りになります。#include <stdio.h> int main(void) { char str[256]; scanf("%s",&str[0]); /* 0番の要素のアドレス */ printf("%s\n",str); return 0; }
このプログラムは、配列名の代わりに、要素0番のアドレスを指定しただけです。
MARIO キーボードから入力した文字列
MARIO
このプログラムの実行結果は、次の通りになります。#include <stdio.h> int main(void) { char str[256] = "DRAGON"; scanf("%s",&str[6]); /* 6番の要素のアドレス */ printf("%s\n",str); return 0; }
このプログラムでは、初期化の段階で配列に DRAGON の文字列を代入しています。
QUEST キーボードから入力した文字列
DRAGONQUEST
つまり、配列名だけを渡している場合、確かに見た目には&をつけていないのですが、
実際に行っていることは、&付きの変数を指定しているのと全く同じなのです。