アドレスとポインタ / ポインタ宣言子 / ポインタと演算 /
配列とポインタ / 関数とポインタ / 関数を指すポインタ
ポインタは、型の一種でコンピュータのメモリアドレスを扱うものです。例えば、プログラムでint a=432;と記述し実行されたとき、Cコンパイラは勝手にメモリアドレスの600番地に変数aを割当て、そこに432のデータを記憶します。ポインタは、この変数aの値が記憶されているメモリアドレス600番地を指示し活用するものです。
ポインタが指すオブジェクトの型で宣言を行う。形式としては*マークをつけるだけ。
宣言例 | 内 容 |
int *pa; | int型のオブジェクトのアドレスを扱う |
double *pb; | double型のオブジェクトのアドレスを扱う |
char *pc; | char型のオブジェクトのアドレスと扱う |
int **pd; | int型のオブジェクトを指すポインタのアドレスを扱う |
*オブジェクト 指定した型に応じた大きさと値をもつデータ記憶領域(変数,配列等)
ポインタ型の変数は、*を付けそのポインタが示すオブジェクトの値を示す。また、&によってオブジェクトのアドレスを得ることができる。*と&は逆の関係にある。
例)int a=432;
pa=&a;
printf("%d\n",*pa);
(*paとしてaと同様に扱うことができる。pa自身で記憶しているは、メモリアドレス600)
配列とポインタ
配列名は、それ自身で配列の先頭アドレスを指すはたらきをもっている。したがって、下図の例ではポインタpとaは同じアドレスを扱っていることになり、アドレスデータの引渡しにおいて&が不要となる。
例) int a[3]={432,333,432};
int *pa;
p=a;
関数の引数にポインタを指定すると呼び出し型のオブジェクトの値を関数内部で直接変更することができる。そのため、以下のような例においてreturn文を使用して関数から値を戻す必要がなくなる。
例)
void kansu(int *x){
(*x)++; /* ポインタxのオブジェクト(a)の値を+1
*/
}
main(){
int a=10;
int *ap;
ap=&a; /* 変数aのアドレスをポインタapに保存
*/
kansu(ap); /* 関数の呼び出し */
}
ポインタapは変数aのアドレスを指している。関数kansuには、この変数aのアドレスを引数として渡し、直接メモリに格納されたaの値を操作している。
ポインタは変数や配列と同様に関数の実効コードが置かれているアドレスを扱うことができる。このポインタの宣言は、指示子に*を付けて(
)でくくり、関数の宣言と同様な形式で行われる。
例) void (*dout)(); /* 関数を指すポインタの宣言(対象の関数は引数,返り値がない)*/
void jap(){
printf("おはようございます\n);
}
void eng(){
printf("Good morning\n");
}
main(){
dout=jap; /* 関数japの実効コードが置かれているアドレスがdoutに保存
*/
*dout(); /* japの実行 */
dout=eng; /* 関数engが置かれているアドレスがdoutに保存
*/
*dout(); /* engの実行 */
}