ポインタを示すポインタ
ポインタとはある変数のアドレスを格納した変数です。
なのでポインタ自体は変数の一種であり、これもアドレスを持ちます。
すなわち、あるポインタ変数のアドレスを指すポインタを定義することが可能です。
ではポインタのポインタを使って何が出来るのでしょうか。
サンプルコード
ソースコード例に見ていきましょう。
pointingpointer_sample1.c
#include <stdio.h> #define LENGTH 32 void initArray(int a[], int aLen) { int i; for (i = 0; i < aLen; i++) a[i] = i; } int main(void) { int i; int arr[LENGTH]; initArray(arr, LENGTH); for (i = 0; i < LENGTH; i++) printf("arr[%d] = %d\n", i, arr[i]); return 0; }
これはint型の配列を参照渡ししています。
配列を引数にとるとそれはポインタを渡すことになります。
ではchar型の配列である文字列だとどうなるでしょうか。
pointingpointer_sample2.c
#include <stdio.h> #define LENGTH 32 void initArray(char a[], int aLen) { int i; a = "after"; } int main(void) { int i; char arr[LENGTH] = "befor"; initArray(arr, LENGTH); printf("%s\n", arr); return 0; }
文字列の場合は参照渡しにはなりません。
なので明示的に参照渡しにする必要があります。
pointingpointer_sample3.c
#include <stdio.h> void setString(char **str) { *str = "test"; } int main(void) { char *str = ""; setString(&str); printf("%s", str); return 0; }
これで文字列の参照渡しが出来ました。
ソースコードを見ればわかると思いますが、
【変数型】 **【ポインタ名】
でポインタのポインタを定義できます。
このときの変数型はポインタ型ではなく定義したポインタが指しているポインタが指している変数の型になります。
少しややこしいですが、最終的にたどり着く変数の型を指定します。
また、「ポインタのポインタのポインタ」というようにいくつでも間接参照できますが、わかりにくいので使われるのはポインタのポインタまでです。