C言語

【C言語 ポインタ】ポインタのポインタ(ダブルポインタ)とは【発展編】

c-language-double-pointer.png

<この記事について>

  • この記事を読むことで、ダブルポインタの仕組みと使い方について理解することができます。
  • 結論としては、ダブルポインタはポインタ変数のアドレスを入れることができ、参照して参照した値を示すことが可能です。関数の引数に使われたり、2以上の多重ポインタも使用可能です。

こんにちは!こんばんは!

ちゃとらです(・ω・)/

ポインタのポインタ(ダブルポインタ)って聞いただけで嫌な感じになりませんか?

でも、ダブルポインタはポインタ変数とほぼ同じで、ただ参照する回数が1回増えただけです。

仕組みが分かればすんなり理解できるかと思います。

ちゃとら

ダブルポインタについて分かりやすく解説していきます!

ダブルポインタとは

説明

ダブルポインタとは、ポインタ変数のアドレスを格納することができるポインタ変数のことです。

役割としてはポインタ変数と同じで、参照して参照した先の値を示すことが可能です。

とあるモブ

う~~ん、よく分かんねぇ…

ちゃとら

そっかぁ、よく分かんねぇかぁ~…

言葉だけだとイメージしにくいと思うので、サンプルコードを交えて具体的な説明をしていきます。

サンプルコード

ダブルポインタを使ってポインタ変数のアドレスを代入し、参照先の参照先の値を表示するプログラムを作ってみました。

#include <stdio.h>

int main(void)
{
	int i = 100;
	int *p;
	int **pp;

	p = &i;   /* ポインタ変数pにiのアドレスを代入*/
	pp = &p;  /* ダブルポインタ変数ppにポインタ変数pのアドレスを代入*/

	printf("iのアドレス:%p\n", &i);
	printf("iの値:%d\n\n", i);

	printf("*pのアドレス:%p\n", &p);
	printf("*pが持っている値:%p\n", p);
	printf("*pの参照先の値:%d\n\n", *p);
	
	printf("**pのアドレス:%p\n", &pp);
	printf("**pが持っている値:%p\n", pp);
	printf("**pの参照先の値:%p\n", *pp);
	printf("**pの参照先の参照先の値:%d\n", **pp);

	return 0;
}
実行結果

iのアドレス:00CFFB8C
iの値:100

*pのアドレス:00CFFB80
*pが持っている値:00CFFB8C
*pの参照先の値:100

**pのアドレス:00CFFB74
**pが持っている値:00CFFB80
**pの参照先の値:00CFFB8C
**pの参照先の参照先の値:100

まずはポインタの役割として、iと*pの関係について説明します。

9行目で*pにiのアドレスを渡しているので、*pの参照先の値はiの値(100)を示します。

また当然ですが、*pが持っている値とiのアドレスが一致していることも分かります。

イメージは以下の図のようになります。

*pとiの関係図

続いてダブルポインタついて説明します。

ダブルポインタの宣言方法は簡単で、ポインタ変数とほぼ同じです。

// ダブルポインタの宣言方法
データ型 **変数名

iと*pと**ppの関係については…

10行目で**ppに*pのアドレスを渡しているので、**ppの参照先の値は*pが持っている値を示し、**ppの参照先の参照先の値はiの値(100)を示します。

またここでも、**ppが持っている値と*pのアドレスが一致しています。

イメージは以下のようになります。

**ppと*pとiの関係

ダブルポインタの使い道

とあるモブ

んー、ダブルポインタの使い道ってなんかあるの?

ちゃとら

代表的なものだと、関数の引数ですね。

ダブルポインタは用途に応じて様々な使い方ができます。

今回はダブルポインタの用途として、関数の引数に使われるパターンを紹介します。

関数の引数

以下のプログラムでは、関数の引数にポインタ変数のアドレスを渡して実行することで、ポインタ変数の参照先が変わります。

#include <stdio.h>

static int num1 = 100;
static int num2 = 200;

// ポインタ変数の参照先をnum1に設定する
void paddressChange1(int **pp)
{
	*pp = &num1;
}

// ポインタ変数の参照先をnum2に設定する
void paddressChange2(int **pp)
{
	*pp = &num2;
}

int main(void)
{
	int *p;

	paddressChange1(&p);
	printf("*p = %d\n", *p);

	paddressChange2(&p);
	printf("*p = %d\n", *p);

	return 0;
}
実行結果

*p = 100
*p = 200

22行目では、関数が実行されることで*pの参照先がnum1になっています。

また25行目では、関数が実行されることで*pの参照先がnum2になっています。

多重ポインタ

ダブルポインタができるのならば、その先のトリプルポインタやクアドアラプルポインタなどの多重ポインタも使用可能です。

以下のプログラムは、一~五重ポインタを使って変数iの値を表示します。

#include <stdio.h>

int main(void)
{
	int i = 100;
	int *p;
	int **pp;
	int ***ppp;
	int ****pppp;
	int *****ppppp;

	p = &i;   
	pp = &p;
	ppp = &pp;
	pppp = &ppp;
	ppppp = &pppp;

	printf("i = %d\n", i);
	printf("*p = %d\n", *p);
	printf("**pp = %d\n", **pp);
	printf("***ppp = %d\n", ***ppp);
	printf("****pppp = %d\n", ****pppp);
	printf("*****ppppp = %d\n", *****ppppp);

	return 0;
}
実行結果

i = 100
*p = 100
**pp = 100
***ppp = 100
****pppp = 100
*****ppppp = 100

16行目で、五重ポインタ*****pppppにポインタのポインタの…ポインタのアドレスを代入してます。

そして23行目で、参照先の参照先の…参照先の値を表示させています。

このように、多重ポインタで一番最後に行き着く参照先の値を表示させることができます。

とあるモブ

でも、多重ポインタでこんな使い方しないでしょ?

ちゃとら

うん、まぁ、そうだね…

とりあえず、「2以上の多重ポインタもあるよっ!」ってことを知ってほしかっただけです…

まとめ

ポインタのポインタ(ダブルポインタ)について

  1. ダブルポインタはポインタ変数のアドレスを入れることができ、参照した参照先の値を示すことができる。
  2. 代表的な使い道としては、関数の引数。
  3. 2以上の多重ポインタも使用可能。
ちゃとら

ダブルポインタは知識として覚えておくといいと思います!

今回はここまでです。

ちゃとら(・ω・)/