[c言語] さっと復習(11) ポインタ

& 変数名

& 変数名で、その変数のアドレスを取得できる。

#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演算子を使うことで、変数や型のバイト単位のサイズを取得できる。

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;
}