ポインタ

基本

char c = 'a';
char* p = &c;

このときpは、cのアドレスを保持します。

int* p;     // intのアドレスを示すポインタ
int** pp;   // intポインタのアドレスを示すポインタ (ダブルポインタ)

int* a[10]; // 10個のintポインタの配列

「*」は型指定子ではなく、直接宣言子に対して付けます。

int* p1, p2, *p3; // p2はポインタ型ではない

間接参照 (dereferencing / indirection)

間接参照とは、ポインタが指し示すオブジェクトを参照することです。そのためにはポインタの前に「*」を置き、次のように記述します。間接演算子とアドレス演算子 | MSDN

char c1 = 'a';
char* p = &c1;

char c2 = *p; // c1を間接参照し、c2は'a'になる
*p = 'b';     // 間接参照しているc1に代入し、c1は'b'になる。このときc2は無関係

初期化していないポインタやNULLポインタへアクセスすると、Visual C++のデバッグ版では次のように報告されます。一方でリリース版では例外コード: 0xc0000005でクラッシュします。

int* p1;
*p1 = 1; // Run-Time Check Failure #3 - The variable 'p1' is being used without being initialized.

int* p2 = NULL;
*p2 = 1; // 例外がスローされました:書き込みアクセス違反。

ポインタ参照 (pointer reference)

ポインタ参照とは、ポインタを参照で渡すことです。pointers - Meaning of *& and **& in c++ - Stack Overflow

void pass_by_value(int* p)
{
    p = new int;
    // 引数は値渡しのため、ブロックを抜けるときにpへの代入は破棄される
}

void pass_by_reference(int*& p)
{
    p = new int;
}

int main()
{
    int* a = NULL;

    pass_by_value(a);
    // aはNULLのまま

    pass_by_reference(a);
    // aにはアドレスが割り当てられている

    return 0;
}

関数ポインタ (Function pointer)

関数のアドレスを取得してポインタを得ることで、そのポインタを利用して関数を呼び出せるようになります。

void Func( int a )
{
}

void main()
{
    void (*f)(int); // 関数ポインタ
    f = &Func;

    f( 123 ); // Func( 123 ) とするのと同義
}

このとき宣言は、次のような構文となっています。

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

なお、関数アドレスを取得するための「&」は省略できます。

void (*f)(int) = &Func;
void (*f)(int) =  Func; // これも可

また関数を実行するのに、関数ポインタの間接参照としても呼び出せます。

  f ( 123 );
(*f)( 123 ); // これも可

難解である関数ポインタの宣言も、typedefで置き換えることで明解になります。

typedef void (*F)();

F f;

関数ポインタを配列に格納することで、呼び出す関数を動的に変更できます。

F fs[] = { &Func1, &Func2, &Func3 };

int a = 1;
fs[ a ](); // Func2()とすることと同じ

メンバ関数ポインタ (Member function pointer) / メンバポインタ

メンバの関数ポインタはメモリのアドレスを示すポインタではなく、構造体のオフセットを示すだけです。一方で静的なメンバは関数ポインタと同様で、アドレスを示します。

class MyClass
{
public:
    void Func1(int a);
    static void Func2(int a);
};
void (MyClass::*f)(int); // メンバ関数ポインタ
f = &MyClass::Func1;

MyClass* class1 = new MyClass();
(class1->*f)(10); // 関数の呼び出し

MyClass class2;
(class2.*f)(10); // 関数の呼び出し


void (*b)(int) = &MyClass::Func2; // 静的なメンバの関数ポインタ
b(10);

コールバック関数 (Callback function)

呼び出し先の関数の実行中に実行されるように、あらかじめ指定しておく関数です。

参考

参考書

STLの関数オブジェクト
C#のデリゲート

voidポインタ (Void pointer)

voidポインタは任意の型を指せます。また関数を指すこともできますが、クラスメンバーは指せません。

void* pv;

ポインタ演算 (Pointer operation)

int p[] = { 10,20,30 };

int a1 = *p;       // 10
int a2 = *(p + 1); // 20
int a3 = *(p + 2); // 30

int* pp = p;
pp++;

int a4 = *pp; // 20

参考

参考書

Microsoft Learnから検索