ポインタ

スポンサーリンク

次のプログラムは,ポインタを扱ったプログラムの例です。

#include <stdio.h>

int main(void)
{
    int num = 123;
    int *ptr;      /* ポインタ変数 */

    printf("%d\n", num);   /* 出力: 123 */
    printf("%d\n", &num);  /* 出力: 460832 (例) */

    ptr = &num;    /* num のアドレスを ptr に代入 */

    ptinrf("%d\n", ptr);   /* 出力: 460832 (例) */
    printf("%d\n", *ptr);  /* 出力: 123 */

    return 0;
}

ポインタとは

ポインタの説明図

ポインタ (pointer) とは,ある変数のメモリアドレスを保持する変数のことです。
今回の例では,ポインタ変数 ptr に,変数 num のメモリアドレスが代入されています。

int 型変数用のポインタは int * ,char 型変数用のポインタは char * というように,ポインタ型は 型 * という型名を持ちます。

アドレス演算子/間接参照演算子

ポインタ関連の演算子として,次のようなものがあります。

演算子説明
& (アドレス演算子)変数のデータが置かれた場所のアドレスを取得
* (間接参照演算子)アドレスの場所に格納されているデータを取得

先のプログラムにおける num, &num, ptr, *ptr は,次のように説明できます。

説明
num変数 num のデータ
&num変数 num のデータが置かれた場所のメモリアドレス
ptr変数 num のデータが置かれた場所のメモリアドレス
*ptrptr の指す場所に格納されたデータ (= 変数 num のデータ)

ポインタの宣言

ポインタの宣言は,次のように書きます。初期化子は省略できます。

int *ptr = &num;

次のような宣言を書くときは注意が必要です。

int *a, b;    /* a は int * 型,b は int 型 */
int *a, *b;   /* a と b は int * 型 */

NULL

ポインタがどの変数も指していない状態は,NULL という定数で表されます。
NULL の値は 0 と定義されています。

ptr = NULL;   /* ptr はどの変数も指していない */

引数のポインタ渡し

C の関数呼び出しは,基本的に値渡しです。
関数の呼び出し元の変数を操作するには,関数の引数に変数へのポインタを受け取り,間接的にアクセスします。

/* a と b の値を交換する */
void swap(int *a, int *b)
{
    int temp = *a;
    *a = *b;
    *b = temp;
}

int main(void)
{
    int m = 1, n = 2;
    swap(&m, &n);  /* アドレスを渡す */
    return 0;
}

scanf 関数で & を付ける必要があったのは,この理由からです。

関数ポインタ

関数への参照を保持する,関数ポインタを宣言することもできます。

int add(int a, int b)
{
    return a + b;
}

int main(void)
{
    int m = 2, n = 5, sum;
    int (*fp)(int, int);  /* 関数ポインタ */

    fp = add;             /* fp は add 関数を参照する */
    sum = (*fp)(m, n);    /* 間接的に add 関数を呼び出し */

    return 0;
}
スポンサーリンク