ポインタの使い方
2012年12月3日:C言語
C言語にはポインタという便利な道具があります。
ポインタを使えるようになると、プログラミングスキルが格段に上昇します。
ここではポインタの使い方を解説します。
メモリってなに
パソコンの仕組みをハードウェアの観点から理解しているとプログラムを組む際に役立ちます。
そこで、はじめにパソコンの仕組みを簡単に説明します。
パソコンは、主にCPUとメモリから成り立っています(ハードディスクもありますがここでは放置します)。
CPUでは計算を行います。
そして、メモリでは一時的な記憶を行います。
例えば、
int a,b,c; a=1; b=2; c=a+b;
int a,b,c;では整数型の変数a,b,cという形で、CPUがメモリに記憶する場所を割り当てます。
メモリには番地があり、番地のことをアドレスと読んでいます。int型の場合は、4バイトなので4つの番地が確保されます。この場合は、3番地にa、7番地にb、11番地にcが割り当てられました。割り当て方はCPUが決めます。
そして、a=1;b=2;でCPUに割り当てたメモリに数字を代入します。
最後に、c=a+b;でCPUがcにa+bという値を計算して代入します。
こうやって、CPUがメモリを使いながら、作業を進めているわけです。
この仕組を理解していることが重要です。
変数のアドレスを知るには
変数のアドレスを知りたい場合は、アンパサンド(&)と呼ばれるポインタ演算子を使えばわかります。
例えば、int a;のアドレスは&aとなります。
ですから、
int a,b; b=0; &b=&a; a=1; printf("%d",b);
とすれば、1が表示されます。このことについて解説します。
まず、int a,b;b=0;では次のようなメモリの割当になっています。
ここで、&b=&a;の命令より、bのアドレスにaのアドレス(6)を代入することになります。すると
となります。最後に、a=1;をすれば、
となりますね。ここでbの値を表示させれば0ではなく1になるわけです。
ポインタ
いきなりアドレス専用の変数を宣言することができます。
例えば、先ほどの例は
int a,*b; *b=0; b=&a; a=1; printf("%d",*b);
というふうに書くことができます。int a,*b;で宣言されたbのことをポインタと読んでいます。ポインタにおけるアドレスの値はアスタリスク(*)をつけることで返すことができます。
*b=0;はポインタbのアドレスの値に0を入れるという操作を示しています。
ポインタ宣言の様式は
です。
ポインタを使ってみる
ポインタは関数を使う際によく使います。
ここでは、ベクトルの和を計算する関数をつくってポインタの威力を実感しましょう。
#include <stdio.h> void func(float *A,float *B,float *C); int main(void){ int i; float A[3],B[3],C[3]; //成分の入力 for(i=0;i<3;i++){ printf("A[%d]=",i); scanf("%f",&A[i]); } for(i=0;i<3;i++){ printf("B[%d]=",i); scanf("%f",&B[i]); } //和の計算 func(A,B,C); //結果の出力 for(i=0;i<3;i++){ printf("C[%d]=%f\n",i,C[i]); } return 0; } void func(float *A,float *B,float *C){ int i; for(i=0;i<3;i++){ *(C+i)=*(A+i)+*(B+i); } }
配列A[3]の場合は先頭の文字だけとったAがポインタとなります。そして
A[0]のポインタ->A
A[1]のポインタ->A+1
A[2]のポインタ->A+2
というふうになります。関数funcに配列A,B,Cのポインタを渡すことで、情報を受け継いでいます。
func内では、
A[0]<–>*A
A[1]<–>*(A+1)
A[2]<–>*(A+2)
B[0]<–>*B
B[1]<–>*(B+1)
B[2]<–>*(B+2)
などの関係を使って、配列Cに計算値をいれています。
直接、配列Cの値を操作しているので、計算が終われば、mainにおける配列Cに計算値が入っています。
このように、
関数に配列の情報を送る際に、ポインタが役に立つわけです。
この使い方はしっかりおさえておきましょう。
著者:安井 真人(やすい まさと)
@yasui_masatoさんをフォロー