質問: ### 前提・実現したいこと C言語からシェルを実行するためのコードを勉強中です。(セキュリティ関連なので、シェルコードです。) C言語の知識は一通り学んだのですが、唐突に出てきた(*(void(*)()) hoge)();というコードの部分が理解できず困っております。(関数ポインタでしょうか?) このコードを実行すると、確かに希望通りの動作をするのですが、(*(void(*)()) hoge)();の部分がなぜ動くのか、自分の力では理解できなかったので、teratailの人々に質問した次第です。 ### 該当のソースコード ``` char *hoge="\x48\x31....."; //シェルコード int main(){ (*(void(*)()) hoge)(); return 0; } ```
回答: 式 `(*(void(*)()) hoge)();` は、構文上次のように分解できます。 * 式全体: 関数呼び出し `{#1}();` * {#1}: 参照はがし `(* {#2})` * {#2}: 型キャスト `({#3}) hoge` {#3}部は関数ポインタ型`void(*)()`、つまり「“引数をとらずvoid型を返す関数”へのポインタ型」です。※注1 少しだけわかりやすく書き直すと、次コードのようになります。 ``` typedef void (*FuncType)(); (* (FuncType) hoge)(); ``` 関数ポインタ型に対する参照はがし(`*`)は明示不要ですから、下記のようにも書けます。※注2 ``` typedef void (*FuncType)(); ((FuncType) hoge)(); ``` ※注1: C言語仕様に厳格に従うと、`void(*)(void)`表記がより望ましいです。`void(*)()`は任意個の実引数を取りうる関数ポインタ型です。この回答では本質ではないため、簡単に「引数なし」と説明しています。 ※注2: C言語仕様に厳格に従うと、関数呼び出しは **常に** 関数ポインタ型を経由します。つまり、普通の関数呼び出しにおいて「関数名から関数ポインタ型への変換」が暗黙に行われています。プログラマがこの型変換を意識することはないでしょう。