& 変数名
& 変数名で、その変数のアドレスを取得できる。
#include <stdio.h>
int main(void) {
int a = 100;
double b = 123.4;
char c = 'c';
// %p はアドレスを16進数8桁で表示
// sizeof(変数名) でその変数のサイズを取得
// 変数名の直前に"&"を付けると,その変数のアドレスを取得
printf("a: value;%10d size;%lu address;%p\n", a, sizeof(a), &a);
printf("b: value;%10lf size;%lu address;%p\n", b, sizeof(b), &b);
printf("c: value;%10c size;%lu address;%p\n", c, sizeof(c), &c);
return 0;
}
sizeof演算子を使うことで、変数や型のバイト単位のサイズを取得できる。
ポインタ変数
ポインタ変数、または単にポインタとは、アドレスを代入するための変数。
変数宣言時に 型 *変数名 または型* 変数名と宣言することで、ポインタ変数となる。
ポインタ変数はとりあえず NULL で初期化しておく、いわゆるNULLポインタ。
ポインタ変数の変数名に * をつけることで、ポインタ変数のアドレスが指し示す値にアクセスできる。
#include <stdio.h>
void show(int, int, int);
int main(void) {
int a = 100;
int b = 200;
// 整数型のポインタ変数pをNULLで初期化。
int *p = NULL;
p = &a;
// ポインタ変数に*をつけると、そのアドレスの値に対応する。
show(a, b, *p);
// p = &a なので、*p、 つまり、aのアドレスの値を400に書き換える。
*p = 400;
show(a, b, *p);
p = &b;
show(a, b, *p);
*p = 800;
show(a, b, *p);
return 0;
}
void show(int a, int b, int p) {
printf("==================\n");
printf("a: value;%10d size;%lu address;%p\n", a, sizeof(a), &a);
printf("b: value;%10d size;%lu address;%p\n", b, sizeof(b), &b);
printf("c: value;%10d size;%lu address;%p\n", p, sizeof(p), &p);
printf("==================\n");
}
ポインタ変数にアドレスを代入せずアクセスすると、Segmentation fault (core dumped) で異常終了する。
#include <stdio.h>
int main(void) {
int *p = NULL;
*p = 1;
return 0;
}
ポインタと関数
c言語では、関数は一つしか値を返すことができない。
ポインタを引数にすることで、実質的に複数の値を返すような関数を作成できる。
変数の値の交換
ポインタ変数を引数に持つ関数にすることで、変数の値の交換ができる。
#include <stdio.h>
void swap(int*, int*);
int main(void) {
int x = 1;
int y = 2;
printf("x: %d, y: %d\n", x, y);
swap(&x, &y);
printf("x: %d, y: %d\n", x, y);
return 0;
}
void swap(int* x, int* y) {
int temp = *x;
*x = *y;
*y = temp;
}