- 締切済み
関数ポインタについて
関数ポインタを使用する際に、 指定する先の関数でデフォルト引数が指定されている場合、 関数ポインタを用いて、その引数を省略して呼び出すことはできるのでしょうか? 以下例とします。 void function(int a = 10){}; typedef void (*test)(int a); test a = &function; a(); //このように呼び出したい
- みんなの回答 (5)
- 専門家の回答
みんなの回答
- kmee
- ベストアンサー率55% (1857/3366)
ちょっと考えてみましょう。 void function0(int a){}; void function1(int a = 10){}; void function2(int a = 20){}; typedef void (*test)(int); test f ; としたときに f = &function0; f = &function1; f = &function2; いずれも正しいですね。では f(); としたら、何を引数に渡したらよいでしょう? void function(int a = 10) は、あくまで void function(int a) であって、 function() としたときに、プロトタイプから判断して funtion(10) としてコンパイルしてくれるだけです。
- chie65536(@chie65535)
- ベストアンサー率44% (8757/19871)
因みに、Visual C++ (Intel x86)の場合、呼出元が積んだスタック上の引数を開放するのは呼出先の責任(デフォルトはstdcall呼び出し規約)なので、呼ばれた先の関数は「引数が1つ積まれている筈だ」として、積まれていない引数を開放しようとして、スタックの操作を行う筈。 すると、引数がある筈の関数を引数を渡さずに呼んだ場合、呼び出し元に帰って来た時点でスタックがズレて、最悪、暴走します。 なので、functionの定義、test型のタイプ宣言で、呼び出し規約も含めて宣言し、そこだけ「呼出元が積んだスタック上の引数を開放するのは呼出元が行い、呼んだ先では操作しないように」と宣言する必要があります(つまり、functionの定義とtestのプロトタイプにcdecl呼び出し規約が必要) 呼び出し規約を理解しないままやると暴走するから「呼び出し規約って何?」ってレベルの場合は「キャストで無理矢理呼び出す」などという下手な考えはしない事。
- chie65536(@chie65535)
- ベストアンサー率44% (8757/19871)
因みに void function(int a = 10){}; typedef void (*test)(void); //testは引数なしで型宣言 test a = (test)(&function); //引数有りを引数無しに無理矢理にキャスト a(); //引数無しで呼び出す なら可能。 あと、C言語って、かなり柔軟性が高いから test a = (test)0x0445E000; //aに0x0445E000をセット a(); //0445e000番地を無理矢理に呼び出す とかって事も可能(0445e000番地のメモリにプログラムが無かったら何が起きるか判らない)
- chie65536(@chie65535)
- ベストアンサー率44% (8757/19871)
>a(); //このように呼び出したい 呼べない。呼ぶとエラーになる。 今のC++やC#の関数定義って「引数の個数や型も含めて定義される」から void function(int a) と void function(void) は「異なる定義になり、二重定義にはならない」のです。 事実、ある処理系では void function(int a) は、外部参照ラベルが __void_function_int としてリンケージエディタに渡され void function(void) は、外部参照ラベルが __void_function_void としてリンケージエディタに渡され、それぞれが異なる関数として実装されます。 なので a(); と書くと「そんな関数は知らん」って言われるか「引数の個数が違う」って言われる事になるでしょう。
- Tacosan
- ベストアンサー率23% (3656/15482)
いいえ.