2011-11-11 31 views
2

私は関数ポインタ宣言と混同しています。私はそのAPIの引数としての私の機能を渡したい場合は関数を関数ポインタとしてcで宣言するにはどうすればよいですか?

void abc(void (*my_func)(void *p), int, int) 

が、私は私の.hファイルでそれを宣言しています:

私はそうのように引数を取るAPI abc()を持っています

void (*xyz)(void *p) 
として

と定義:

void *(xyz)(void *p){ 
statements; 
} 

が、これはエラーをスローします。私を修正してください。

答えて

4

あなたはそれを宣言する必要があります:

void xyz(void *p); 

実装と同じように。

あなたのAPIに渡し

は、型システムが自動的にそれを割り出し:

abc(xyz,someint,anotherint); 
3

(*xyz)は、それが関数ポインタであることを意味します。

ファンクションポインタは、typedefで最もよく処理されます。だから間違いがないことが保証されています。

私は、次の操作を行います:

// define a type for the function (not its pointers, as you can often read) 
typedef void my_func_t(void *p); 

void abc(my_func_t*, int, int); 

// declaration in order to be type-safe - impossible if only the pointer would be typedef'd 
my_func_t my_func_impl; 

// definition: 
void my_func_impl(void *p) 
{ 
    do_something_with(p); 
} 

、その後、あなたはabc(my_func_impl, 47, 11)とあなたのabc()を呼び出すことができます。 my_func_implの前に&を置いて、取得したい機能アドレスであることを指摘することができますが、これはオプションです。

代替は

typedef void (*my_func_p)(void *p); 

を書いて、my_func_pの代わりmy_func_t *を使用することですが、これは、あなたがmy_func_t my_func_impl;を書くことができないという欠点があります。

なぜそれをしたいですか?

まあ、いずれかの偶然や事故、typedefでは変更されまたは関数定義によって、彼らはもはや一致しませんが、衝突がエラーとして宣言されますが、されていない場合にのみ、警告として(ミスマッチポインタ) 。 OTOH、は、プロトタイプの一種として機能し、エラーである機能ヘッダーの不一致が発生します。

+1

私はこれを 'typedef void(* my_func_ptr)(void *);'と呼ぶことがあります。 –

+1

はい、私もそうです。しかし、 'my_func_t my_func_impl;でこのトリックはもうできません。私は編集します。 – glglgl

+0

違反はありませんが、自分自身を含む多くのプログラマーは 'my_func_t my_func_impl;'を見て、それがグローバル変数であり、おそらく関数ポインタだと思います。それはプログラマーではなく、コンピューターのための良い例です。このような手口は、[Linuxカーネルの 'typedef'に対する厳しい制限(http://www.kernel.org/doc/Documentation/CodingStyle)(第5章「Typedefs」)をもたらしました。 –

0

「ABC」の第一引数の関数のポインタが「無効」を返すと、引数として「無効*」を有するされて...

だからあなたのコードは次のようになります。

void 
myFunc (void *) 
{ 
    // ... my statements 
} 

... 

abc (myFunc, 10, 20); 
1

私が正しく理解していれば、xyzabcに渡される関数になりますか?

void xyz(void *p); 

そして:引数my_funcが示すように

は、あなたが引数としてvoid *を取り、void

type (*func_pointer)(type, type, type, .......) 
^^ ^ ^ ^ ^
    | |  |  |  |  | 
    | |  |  argument types 
    | | pointer name 
    | This is a function pointer 
return type 

はそのため、あなたにxyzを宣言する必要が返す関数へのポインタを持っています同じ実装:

void xyz(void *p){ 
    statements; 
} 

あなたが間違っているのは、.hファイルに書いた行がxyzという名前の関数ポインタを定義しているということです。あなたはxyz = some_function;

を書いたことがないので、関数ポインタを使用すると、ソースファイルに記述されているもの、値を持たない入力としてvoid *を取り、あなたの意図だったvoid *、代わりのvoidを返すも名前xyzの関数であり、 。

あなたがint *x;を書き、xintへのポインタです:

は、たぶん、これはあなたがあまり混乱して得ることができます。次にint y;には*がなく、x = &y;と書かれています。

機能と同じです。 void (*funcptr)(void *p);がある場合は、void some_func(void *p){}(やはり余分な数字は*なし)と書かれた関数があり、funcptr = some_func;と書いてください。 &は実際には関数名が関数のポインタであるため、必要ありません。あなたはもっと明示的にそれを置くことができます。

void xyz(void *p); 

void xyz(void *p){ 
    // ... 
} 

とは、APIへのポインタを渡します:適切な場合には

abc(xyz, 42, 7); 

関数名が自動的に関数ポインタとして解釈されますが、他のと同じように

+0

これは最高の答えだと思います。この問題の根本原因を明確に説明しています。非常に役立ちます!ありがとう。 –

1

単に宣言し、あなたの関数を定義します。

abc(&xyz, 42, 7); 
0

これは

void abc(void* (*my_func)(void*), int a, int b) { 
    my_func(0); 
} 

void *(xyz)(void *p) {} 

int main() { 
    abc(xyz, 0, 0); 
    return 0; 
} 

働くあなたがvoid (*my_func)(void *p)を書くときには、ボイド とを返す関数へのポインタを、意味:簡潔にはあなたのものでない場合にも、明示的に、関数のアドレスを取ることができますvoid (*my_func)(void *p)これは、ポインタを返す関数へのポインタを意味します。

関連する問題