equal_l2’s blog

※記載されている内容の正確性は保証しませんが、間違いを指摘していただければ直します。

ポインタを学ぶ(2) 特別なポインタ

ポインタの実際の用途について学ぶ前に、少し特別なポインタについて学んでみる。

配列とポインタ

C/C++の配列はポインタによって実装されている。
たとえば、int a[20]を宣言したとする。
これが宣言されると、メモリ上にint型の領域が20個連続した領域に確保される。
連続した領域というのがミソで、これによって、先頭要素のアドレスさえわかればそのアドレスに加算していけば任意の要素にアクセスできる。
こういうわけで、配列先頭要素のアドレスは重要なので、配列名を単独で書くと配列先頭要素へのポインタになる

この文法によって、配列要素へのアクセスにはいくつかの書き方がある。具体的にはこうだ。

// iは整数
*(a+i)
a[i]

正確には、上の書き方がむしろ本来の書き方で、下の書き方はその簡略版である、と言ったほうがいいかもしれない。

aとiは逆にしてもいいので、こんなのも同じ意味になる。

i[a]

競技プログラミングくらいでしか使わないだろうが。

関数ポインタ

実は、関数もメモリ上に場所をとるので、アドレスが存在する。
関数へのポインタは書き方がやや複雑だ。
次のような関数があるとする。

//Tは型名
T test(void)

別に引数がvoidである必要はない。説明を簡単にするためである。

この関数のアドレスを取得するには次のようにする。

test
// &test とも書ける

配列名と似たような感じで、関数名も関数へのポインタになるのだ。

アドレスがある以上、これを格納するポインタもある。
ある関数へのポインタの宣言は、次のように書ける。

戻り値の型(*ポインタ名)(引数の型);

さて、関数ポインタを宣言した。
これをどう使うかというと、結局のところは関数を呼び出すのに使うのだ。
関数ポインタに格納された関数を呼び出すには次のようにする。

(*ポインタ名)(引数);
// ポインタ名(引数); と書くこともできる


具体的に、関数ポインタtpを宣言して、test関数を格納して、呼び出してみる。

T(*tp)(void); //関数ポインタ tp の宣言
tp = test; // tp に test のアドレスを代入
(*tp)(); // tp() とも書ける。tpに格納されたアドレスにある関数を呼び出し

次回こそは、ポインタの実際の用途について学ぶ。

2014/3/14 関数ポインタから関数を呼び出す方法を追記
2016/2/3 解説を詳しくした