8-2 間接参照

この記事は約3分で読めます。

関節参照演算子

C言語のポインタは、単にアドレスを取得するためにあるのではありません。ポインタはアドレスを介して別の変数を指すことができます。つまり、ポインタを使うと別の変数にアクセスしたり値を書き換えることができます。これがポインタの肝です。ポインタ名に対して間接演算子*を使うとポインタが指す変数にアクセスできます。NULLおよびNULLが格納されるポインタに対して間接演算子を使用してはいけません。

例えば、

int *p;
int n;
p=&n;

とすると、pはint*型となります。pにnのアドレスを代入すると、pはnを指すようになります。*pはnと同じになるので、*pはint型になります。

#include <stdio.h>
int main(void){
	int a=0,b=0;
	int *pn;
	pn=&a;
	a=10;
	printf("a=%d,*pn=%d\n",a,*pn);
	pn=&b;
	*pn=6;
	printf("b=%d,*pn=%d\n",b,*pn);
	return 0;
}

実行結果

a=10,*pn=10
b=6,*pn=6

このプログラムではまずポインタ変数pnにaのアドレスを代入しています。すると、pnはaを指すことになり、*pnはaと同一となります。aの値を変えると*pnの値も変わります。次に、pnにbのアドレスを代入しています。pnはbを指すようになり、*pnはbを同一になります。*pnの値を変えると当然bの値も変わります。

ポインタを引数に使う

ポインタ型の変数を関数の引数に使うことができます。関数の引数にポインタを使用すると、呼び出し元の値を書き換えることができます。

#include <stdio.h>
void calcWa(int a,int b,int ans){
	ans=a+b;
}
int main(void){
	int a,b,wa=0;
	scanf("%d%d",&a,&b);
	calcWa(a,b,wa);
	printf("wa=%d\n",wa);
	return 0;
}

実行結果

5 -9
wa=0

まず、ポインタを使わずに仮引数に値を代入しても、変数waの値は0のままです。これは、関数の仮引数は実引数の値がコピーされるだけで関数に変数そのものを渡しているわけではないと説明しました。このプログラムをポインタをつかって書き直します。

#include <stdio.h>
void calcWa(int a,int b,int*ans){
	*ans=a+b;
}
int main(void){
	int a,b,wa=0;
	scanf("%d%d",&a,&b);
	calcWa(a,b,&wa);
	printf("wa=%d\n",wa);
	return 0;
}

実行結果

5 -9
wa=-4

関数calcWaの第3引数をint*型に書き直します。変数waのアドレスを渡し、ポインタを通して値を書き込みました。よって、正しい和が出力されます。

scanfの引数の正体

今までは関数を呼び出すときは引数に変数を指定していましたが、scanf関数のみ変数名に&をつけなければならないと説明しました。これは、scanf関数はポインタを介して値を書き込む必要があるからです。&をつかないと値を渡すことになり、値を書き込めません。

まとめ

間接参照演算子を用いるとポインタに対してポインタが指す変数にアクセスできる。

scanf関数を呼び出すときに使用していた&はアドレスを渡すための演算子だった。

コメント