ポインタ変数
char *x = "hello";
ポインタ変数*x
は、hello\0
が格納された場所のアドレスを持っている。
ポインタ変数*x
が格納してるのは、値そのもの(ここではhello\0
)ではなく、(値を格納しているメモリ上の)”アドレス”である。
アドレス演算子
&x
とは、変数x
のアドレスのこと。
&x
は変数x
のアドレスなのだから
int *x_ptr = &x;
とすると、ポインタ変数x_ptr
に変数x
のアドレスを直接代入できる。
これで、ポインタ変数x_ptr
に変数x
のアドレスを格納できた。x_ptr
は変数x
をポイントしてる(指し示してる)。
間接演算子
*ポインタ変数
というフォーマット。
int32_t a = 8;
int32_t *a_ptr = &a;
printf("%i", *a_ptr); // => 8
// ここの *a_ptr が間接演算子
間接演算子*
をポインタ変数a_ptr
に適用すると、a_ptr
が指し示しているアドレスにある値を取り出す。
*a_ptr
とは、ポインタ変数a_ptr
がポイントしてるとこにある値なのだから、
*a_ptr = 99;
printf("%i", a); // =>99
のように、代入(上書き)ができる。
ちなみに、最後のprintf
は間接演算子を使って
printf("%i", *a_ptr);
でも同じ結果。
int32_t *a_ptr = &a;
を省略することもできる:
int32_t a = 8;
printf("%i", *&a);
(&a
に対して直接、間接演算子*
を適用してる)
配列とポインタ
#include <stdio.h>
int main()
{
int32_t a[] = {123, 4545, 999};
int32_t *a_ptr = a; // 配列名を直接ポインタ変数に与えると、その配列の先頭要素のアドレスが得られる(アドレス演算子は不要)
printf("%i\n", *a_ptr); // 間接演算子
a_ptr = &a[1]; // 配列中の個々の要素に対しては、アドレス演算子が必要
printf("%i", *a_ptr); // 間接演算子
}
$ ./a.out
123
4545
ポインタとインデックス
ポインタ変数p
に対して、p[i]
は間接演算子*(p + i)
に等しい。
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
int main()
{
int32_t array[] = {1, 2, 3, 4};
int32_t *p = array;
for (size_t i = 0; i < sizeof array / sizeof(int32_t); i++) {
printf("%i\n", p[i]); // p[i] is *(p + i)
}
}
実行すると
$ ./a.out
1
2
3
4
関数ポインタ
関数のアドレスを格納したポインタ変数が「関数ポインタ」。
関数ポインタ変数の宣言
返り値の型 (*ポインタ変数名)(パラメータリスト)
compare
関数へのポインタ変数p
を定義するには
int compare(int x, int y);
int (*p)(int, int) = compre; // 「*p = &x」と対応
最後の行にあるように、関数のアドレスを渡す際は関数名を与える。&compareとかcompare()じゃない。
&compare
でも可ということでした(コメントより)。
パラメータリストの部分は型だけでよい(つまり(*p)(int x, int y)
と書かなくても大丈夫)。
関数ポインタの間接演算子
(*ポインタ変数名)(パラメータリスト)
または
ポインタ変数名(パラメータリスト)
compare
関数のポインタ変数を定義して、間接演算子で関数を呼び出す例:
int compare(int x, int y);
int (*p)(int, int) = compare; // 関数compareへのポインタ変数p
// 下の二行は同じ結果になる
printf("func result: %i", (*p)(3, 4));
printf("func result: %i", p(3, 4));
typedef
と関数ポインタ
int (*fptr1)(int);
int square(int num) {
return num * num;
}
int n = 5;
fptr1 = square;
printf("squared: %d", fptr1(n));
typedef
を使って書くと
typedef int (*funcptr)(int); // funcptr型が使えるようになる
funcptr ftp2;
ftpr2 = square;
printf("squared: %d", fptr2(n));