![]() |
|
C言語の要「ポインタ」コンピュータのメモリ構造と変数の関係を通し、C言語の特徴であるポインタを理解する ではこれからC言語の中で最もよく使われ、C言語の要である「ポインタ」について説明をします。これを理解すると、今まで何も言わずに隠してきた「文字列をどう扱うか」という問題や、「キーボードから文字を入力するには」という事の理解の助けになります。 変数はどこにある?●メモリは土地、アドレスは住所
●変数さんが引っ越してくる 変数を宣言すると、コンピュータのメモリ空間のどこかにその変数が割り当てられます。どこかは分かりませんし、意識する必要もありません。例えると、宣言とは変数iさんがそこに住むということに似ています。住むからには「住所」が必ずあります。上の絵の場合は、「0番地」です。iさんが初めてそこに来たとき、そこにある立て札には、何が書いてあるか分かりません。昔住んでいた人がそのままにしている場合があるからです。iさんはそこに住むことを決めてから、その土地の立て札を、自由に書き換えることができます。 このたとえ話を踏まえたうえで、実際の話に戻りましょう。変数が宣言されると、それはメモリのどこかに割り当てられます。そして変数はその「どこか」のアドレスをもつことになります。変数はメモリ上で位置を割り当てられるだけなので、割り当てた場所にどんな数値が入っているか分かりません。0の場合もあるし、そうでない場合もあります。 例えば次の例を実行してみてください。この例は、宣言したあとに代入をしていないので、どんな値が出てくるか分かりません。(コンパイラによっては「警告: iの値が未定義」などとエラーがでますが、コンパイルはできます)
●変数iさんは金持ちだった
つまり変数さんは、区切られた区画を越えて住むことができるわけです。でもそうすると住所はどうなるのでしょうか。右図の場合、住所は「933」になります。変数のアドレスは、割り当てられたメモリの先頭のアドレスになるわけです。 何だかめんどくさそうですが、プログラマはそんなことを気にすることなく、使うことができます。もし変数iに1000を代入すると、int型を2バイトで表現するシステムでは、右図のように2バイトを使って1000を表現してくれます。 ●ところで、どこに住んでるの? 変数さんは、どこに住んでいるのかを教えてくれます。教えてもらうには、アドレス演算子「&」をつけます。例えば printf("%d\n", &i);
と書けば、変数iさんのアドレスが分かります(通常は"%p"を指定しますが、説明の便宜上、"%d"を使用しています)。 ポインタ変数●住所を覚えるpさん C言語ではその住所を記憶するだけの変数を作ることも可能です。この変数をポインタ変数といいます。この変数は重要なので、しっかり理解してください。 宣言の方法は、 int *p; のように、変数名の前に「*」をつけます。ここで注意したいのは、「int」です。これはポインタ変数がint型なのではありません。int型の変数を指し示すために使うポインタ変数pを宣言したことになります。つまり、int人の住所を覚えるpさんがやってきた、ということです。 pさんに、さきほどのiさんの住所を教えるには、 p = &i; と、します。つまりこの時点で変数pには、変数iのアドレスが入ったことになります。 pさんは、iさんの住所を知ったわけですから、iさんの家へ行くことができます。立て札にはどんな数字が書いてあるかを知ることができます。pさんに見てきてもらうには、間接演算子「*」をつかいます。ポインタを宣言したときに使った「*」とは違うので注意。
ちょっとややこしくなってきましたが、これを順に理解すると、以下のようになります。
●pさん、実は犯罪者。 もう何となく分かったと思いますが、pさんは頭に*をつけられると、iさんのように振る舞います。だから、iさんになりすまして、立て札を書き換えることもできます。 p = &i; *p = 100; とすると、変数iは「100」になってしまいます。注意。このコードの1行目は絶対はぶいてはいけません。なぜならpさんが引っ越してきたばかりのときは、その土地には詳しくないので、住所を教えてあげなくてはいけないのです。もしpさんが偶然にも永田町の住所(プログラムの置かれたメモリ領域)を覚えていたらどうなるでしょうか。ある日突然国会議事堂の立て札が「100」になっていた...立て札の数字が命の政治機能はその場で停止してしまいます。 このように、ポインタ変数を使うときは、必ず変数として確保されたアドレスを指すようにする、たとえば p = &i; 等として、どこかの変数のアドレスを入れておくことが絶対条件になります。 だから、何。ちょっとコレだけではポインタがなぜ重要だといわれるのか、良くわかりませんね。しかし文字列を扱う問題、キーボードから文字を入力するという問題に必ずついて回るのが、このポインタなのです。ポインタの特徴は、「アドレスを覚えられる」という、その一点だけです。しかし、アドレスを知っているということはそのメモリの内容をいじることができるということになるのです。これが重要なことです。 つまり、変数の内容ではなく、「変数自体」を扱いたいという場合に、ポインタは威力を発揮します。少しネタをばらすと、例えばキーボードから文字を入力する場合はscanfという関数を使いますが、この関数には変数ではなく、変数へのポインタを渡します。するとscanfは、そうやって教えてもらったアドレスのメモリへ、キーボードから入力された文字を書きこむのです。 まぁ、これについては次回、詳しくお教えしましょう。 まとめ。
(1997/01/31 公開, 1999/03/13 改) |
![]() |
著作権は全て小出 俊夫にあります。KID's World © 1996-2003 Toshio Koide.