char c = 'a'; char* p = &c;
このときpは、cのアドレスを保持します。
int* p; // intのアドレスを示すポインタ int** pp; // intポインタのアドレスを示すポインタ (ダブルポインタ) int* a[10]; // 10個のintポインタの配列
「*」は型指定子ではなく、直接宣言子に対して付けます。
int* p1, p2, *p3; // p2はポインタ型ではない
間接参照とは、ポインタが指し示すオブジェクトを参照することです。そのためにはポインタの前に「*」を置き、次のように記述します。間接演算子とアドレス演算子 | 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; // 例外がスローされました:書き込みアクセス違反。
ポインタ参照とは、ポインタを参照で渡すことです。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; }
関数のアドレスを取得してポインタを得ることで、そのポインタを利用して関数を呼び出せるようになります。
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()とすることと同じ
メンバの関数ポインタはメモリのアドレスを示すポインタではなく、構造体のオフセットを示すだけです。一方で静的なメンバは関数ポインタと同様で、アドレスを示します。
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);
呼び出し先の関数の実行中に実行されるように、あらかじめ指定しておく関数です。
voidポインタは任意の型を指せます。また関数を指すこともできますが、クラスメンバーは指せません。
void* pv;
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