[解決済み】関数ポインタの定義にアンパサンド '&' やアスタリスク '*' がいくつあっても大丈夫なのはなぜですか?
質問
なぜ、次のような仕組みになっているのでしょうか?
void foo() {
cout << "Foo to you too!\n";
};
int main() {
void (*p1_foo)() = foo;
void (*p2_foo)() = *foo;
void (*p3_foo)() = &foo;
void (*p4_foo)() = *&foo;
void (*p5_foo)() = &*foo;
void (*p6_foo)() = **foo;
void (*p7_foo)() = **********************foo;
(*p1_foo)();
(*p2_foo)();
(*p3_foo)();
(*p4_foo)();
(*p5_foo)();
(*p6_foo)();
(*p7_foo)();
}
解決方法は?
これには、これらの演算子の組み合わせがすべて同じように動作するようにするための、いくつかの断片があります。
これらがすべて機能する根本的な理由は、関数(例えば
foo
) は、暗黙のうちに関数へのポインタに変換されます。 このため
void (*p1_foo)() = foo;
が動作します。
foo
は暗黙のうちに自分自身へのポインタに変換され、そのポインタは
p1_foo
.
単項の
&
を関数に適用すると、オブジェクトに適用するとオブジェクトのアドレスが得られるのと同じように、関数へのポインタが得られます。 通常の関数へのポインタの場合は、暗黙のうちに関数から関数へのポインタに変換されるため、常に冗長です。 いずれにせよ、このような理由で
void (*p3_foo)() = &foo;
が機能します。
単項の
*
関数ポインタに適用すると、オブジェクトへの通常のポインタに適用したときと同じように、指されたオブジェクトを生成します。
これらのルールは組み合わせることができます。 最後から2番目の例を見てみましょう。
**foo
:
-
最初に
foo
は暗黙のうちに自分自身へのポインタに変換され、最初の*
がその関数ポインタに適用され、その結果、関数foo
を再び使用します。 -
そして、その結果を再び暗黙のうちに自分自身へのポインタに変換して、2番目の
*
が適用され、再び関数foo
. - その後、再び関数ポインタに暗黙のうちに変換され、変数に代入されます。
をいくつでも追加することができます。
*
を好きなだけ使っても、結果はいつも同じです。 より多くの
*
があればあるほど、楽しい。
5つ目の例も考えてみましょう。
&*foo
:
-
最初に
foo
は暗黙のうちに自分自身へのポインタに変換されます。*
が適用されfoo
また -
次に
&
に適用されます。foo
へのポインタを生成します。foo
となり、変数に代入される。
は、その
&
は関数にしか適用できませんが、関数ポインタに変換された関数には適用できません (もちろん、関数ポインタが変数の場合は例外で、その場合は結果は関数へのポインタになります; 例えば、リストに
void (**pp_foo)() = &p7_foo;
).
このため
&&foo
は機能しません。
&foo
は関数ではなく、rvalueである関数ポインタです。 しかし
&*&*&*&*&*&*foo
と同じように動作します。
&******&foo
というのは、これらの表現ではどちらも
&
は常に関数に適用され、rvalue関数ポインタには適用されません。
また、単項の
*
は、関数ポインタを介して呼び出すことができます。
(*p1_foo)();
と
(p1_foo)();
が同じ結果になるのは、やはり関数から関数ポインタへの変換が原因です。
関連
-
[解決済み] gdbを使用してもデバッグシンボルが見つからない
-
[解決済み] 要素ごとの加算は、結合ループよりも分離ループの方がはるかに高速なのはなぜですか?
-
[解決済み] C++11では、標準化されたメモリモデルが導入されました。その意味するところは?そして、C++プログラミングにどのような影響を与えるのでしょうか?
-
[解決済み] 仮想デストラクタはいつ使うのか?
-
[解決済み] 0.1fを0にすると、なぜ10倍もパフォーマンスが落ちるのですか?
-
[解決済み] template "と "typename "キーワードはどこに、なぜ入れなければならないのですか?
-
[解決済み] switch文の中で変数を宣言してはいけないのはなぜですか?
-
[解決済み] 難読化Cコードコンテスト2006。sykes2.cの解説をお願いします。
-
[解決済み] 実際の関数定義と比較して)パラメータがない関数がコンパイルされるのはなぜですか?
-
[解決済み】画像処理。コカ・コーラ缶」認識のためのアルゴリズム改良
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】構造体のベクター初期化について
-
[解決済み】C++ クラスヘッダが含まれているときに「不明な型」があるのはなぜですか?重複
-
[解決済み】getline()が何らかの入力の後に使用されると動作しない 【重複あり
-
[解決済み】fpermissiveフラグは何をするのですか?
-
[解決済み】指定範囲内の乱数で配列を埋める(C++)
-
[解決済み】CMakeエラー at CMakeLists.txt:30 (project)。CMAKE_C_COMPILER が見つかりませんでした。
-
[解決済み】std::cin.getline( ) vs. std::cin
-
[解決済み] to_string は std のメンバーではない、と g++ が言っている (mingw)
-
[解決済み】変数やフィールドがvoid宣言されている
-
[解決済み】'std::cout'への未定義の参照