event
オブジェクトや式ではなく、typeです。構造体型のメンバーにはアクセスできず、構造体型のオブジェクトにのみアクセスできます。
与えられた:
typedef struct {
void* fn;
void* param;
} event;
type のオブジェクトがevent
必要であり、そのメンバーに値を割り当てる必要があります。
あなたの質問ではfn
、メンバー名として を使用していますが、 という名前を参照していますfunction
。ここでは、それらは同じものであると仮定し、それfn
は何らかの機能を指しているはずです。
関数ポインターを移植可能に格納することはできませんvoid*
。多くの、おそらくほとんどの実装では、それを回避できますが、言語によって保証されていません。(関数ポインタがデータ ポインタよりも大きく、関数ポインタを変換するとvoid*
情報が失われるシステムがあります。) 一方、すべてのポインタから関数への型は相互に変換可能であり、往復変換が保証されます。元のポインター値を提供します。
引数を取り、結果を返さないfn
関数を指し示す必要があると仮定します (多くの情報を提供しなかったため、ここでは多くの仮定を行っています) 。void*
それからaを作るparam
のvoid*
は理にかなっています。その仮定との一貫性を保つために、型定義を変更できます。
typedef struct {
void (*fn)(void*);
void *param;
} event;
(void (*fn)(void*);
構文は完全には明らかではありません。私はcdecl
それを構築していました。)
これで、 type のオブジェクトを定義できますevent
:
event e = { some_func, NULL };
some_func
次のように、どこかで定義する必要があります
void some_func(void *param { /* ... */ }
または同等のもの。event
これで、オブジェクトを介して間接的にその関数を呼び出すことができますe
:
e.fn(e.param);
または、へのポインターを持っている方が便利な場合event
:
event *ptr = malloc(sizeof *ptr);
if (event == NULL) {
/* error handling here */
}
ptr->fn = some_func;
ptr->param = NULL;
また、ポインターへのポインターと、それが指すオブジェクトにevent
含まれる関数ポインターの両方で間接化を使用できます。event
ptr->fn(ptr->param);
達成しようとしていることに応じてfn
、さまざまなタイプの関数を指すことができます。それを行う場合は、(明示的なキャストを使用して) 変換するか、それを介して呼び出す前に、それが指す関数の実際の型に変換する必要があります。異なる型の関数ポインターをやみくもに混在させることはできません。その場合、結果はコンパイル時エラーまたは実行時の未定義の動作になります。(パラメーターなしで結果を返さない関数へのポインター) を「ジェネリック」関数ポインター型として使用できますが、必要な型への変換とは異なり、明示的である必要があります。)e.fn
ptr->fn
void (*)(void)
void*
追加のパラメーターを使用する場合と使用しない場合の両方で関数呼び出しを行う方法を知りたいですvoid*
。
引数なしで関数を呼び出すには、単に()
関数呼び出しで使用します。ただし、特定の関数については、パラメーターを指定して呼び出すかどうかを選択することはできません。呼び出しは定義と一致する必要があります。(おそらく のような可変引数関数を除きprintf
ますが、それでも正しい型の関数ポインタが必要であり、引数なしで可変引数関数を呼び出すことはできません。)