私は、GTK +コードでシグナルハンドラを設定するという問題に何度もぶつかりつつあります。いくつかのパラメータを必要とせず、ハンドラのシグネチャが異なる複数のシグナルのハンドラと同じ関数を使いたいと思います。議論(私が気にすること)は同じです。Cの関数を、予想以上の引数で呼び出しても安全ですか?
GObject APIに関数へのポインタを渡すのは、実際の意味ではなく、未定義の動作ではありません。議論はシグナル放出プロセスから実際に得られるよりも?
または、これをGTK +と離婚するには、このコードは大丈夫ですか?
/* Note: No void *userdata argument! */
void show(int x) {
printf("x = %d\n", x);
}
void do_stuff(void (*fn)(int, void *), void *userdata) {
static int total = 0;
(*fn)(total, userdata);
total++;
}
void doitnow(void) {
do_stuff(&show, NULL);
}
さらに詳しい情報については、関数シグネチャとコールサイトの間で異なる戻り値の型がどのような意味を持つかを検討してください。
編集:より密接almost-identical questionプローブ「互換性のある機能の種類」、およびan answer directly addressing my concrete problemを描く - GObjectの信号ハンドラを連鎖すること。 TL; DR:はい、それは未定義の動作ですが、実際には(いくつかのツールキットでは必須ではありませんが)慣用的です。
このように関数ポインタをUBに変換することはほぼ確実です。 – Flexo
@Flexo関数ポインタを変換しても問題ありません。これを逆変換以外の目的で使うと、... –
ところで、do_stuffでは '(* fn)'は必要ありません。 'fn(total、userdata)'を呼び出すだけです。 'fn'は関数ポインタであるため、関数呼び出し演算子'(total、userdata) 'は、あなたが期待するものとまったく同じです。 – Jens