2016-11-17 13 views
1

関数のパラメータから関数ポインタを戻すことができません。 ここに私がしようとしているものの例があります。ネットを検索Cの関数引数から関数を取り出す方法は?

int a(int I) 
{ 
    return I*I; 
} 

void get_a(int(*R)(int)) 
{ 
    R = &a; 
} 

int main() 
{ 
    int(*function)(int) = NULL; 

    printf("function a=%p\n", a); 

    get_a(function); 
    printf("function a=%p\n", &function); // Is never the right address. 

    return 0; 
} 

は、私が唯一のパラメータとして関数を渡すの例を見つけることができ、助けにはならなかったので、私はあきらめ、自分でこの問題を解決しようとしました。

+0

これは、「関数の引数からintを取得する方法」と同じです。最初にその問題を解決すれば、この問題も理解できます。 –

+0

あなたの関数get_a()は何もしません。なぜなら、それが行うのはローカル変数に割り当てられてから何も返さないからです。良いコンパイラはそれを完全に最適化するかもしれません。 –

答えて

2

ここには2つの問題があります。

まず、関数がローカル変数を変更しているため、結果は呼び出し元に反映されません。関数ポインタ変数のアドレスを渡してから、get_aに関数ポインタへのポインタを受け入れる必要があります。変数のアドレスを渡すことで、参照を逆参照して変更することができます。

第二の問題は、2番目のprintffunctionアドレスの代わりに、そのを印刷しているということです。値を渡します。

void get_a(int(**R)(int)) 
{ 
    *R = &a; 
} 

int main() 
{ 
    int(*function)(int) = NULL; 

    printf("function a=%p\n", (void *)a); 

    get_a(&function); 
    printf("function a=%p\n", (void *)function); 

    return 0; 
} 

結果:

function a=0x400498 
function a=0x400498 

はまたvoid *へのキャストに注意してください。 printfへのポインタを%p経由で印刷することは、まれに、void *へのキャストが必要な場合の1つです。そうでないと、未定義の動作になる可能性があります。

+0

実例を使って早急に返信いただきありがとうございます。余分な*と&といくつかの組み合わせを試してきましたが、明らかにこれはありません。 –

+0

@PuzzlingProgrammer私は助けてくれると嬉しいです。あなたが役に立つと思ったら、[この回答を受け入れる](http://stackoverflow.com/help/accepted-answer)を自由に感じてください。 – dbush

+0

これはどちらの場合でも 'printf(" ...%p ... "、(void *)whatever)'にするか、動作が未定義です。 (これは単にポインタを扱うためだけではなく、 'printf'は可変的なものなので、ポインタの自動変換は行われません;%pの引数は、その型がすでにvoid '[const] void *'または(C11のみ) '[const] char *'です。 – zwol

3

最初の問題は、その値ではなくfunctionポインタへのポインタを出力することです。それは決してあなたに正しい住所を与えることはありません。

この問題が解決しない場合、残りの問題はRが値渡しの関数ポインタであることです。 get_aの内部の変更は、関数のローカルなので、functionの値がmainに反映されません。すなわち、get_aへのポインタを関数へのポインタを渡して、間接参照を割り当てる

  • get_aリターン関数ポインタを作成し、mainfunction = get_a()を割り当てる

    、または
  • は、次の2つのこの問題の解決策を持っています非関数ポインタに使用するのと同じテクニックを使用します。ここで

あなたは第二のアプローチを実装する方法です。

void get_a(int(**R)(int)) { 
    *R = a; 
} 
... 
get_a(&function); 

Demo.

注: ISO Cはvoid*に関数ポインタの変換を禁止し、で印刷するために必要とされるものです%p。私はあなたがデバッグ目的のためにそれをやっていると仮定します。

+0

第1のアプローチへの解決策は 'int(* get_a())(int){return&a;}'でなければなりません。メッシー。 –

+0

好奇心:ISO Cは 'uintmax_t(またはuintptr_t)p =(cast_to_type)function_ptr''を許可しますか?宛先タイプが 'function_ptr'のすべてに対して十分に広くない場合でも? – chux

+1

@chux良い質問ですが、わかりません。 – dasblinkenlight

関連する問題