web-dev-qa-db-ja.com

関数ポインターを使用して関数を呼び出す方法は?

次の3つの機能があるとします。

bool A();
bool B();
bool C();

関数ポインターを使用してこれらの関数の1つを条件付きで呼び出す方法、および関数ポインターを宣言する方法を教えてください。

29
Priya

次のことを実行できます。A、B、Cの機能が次のようになっているとします。

bool A()
{
   .....
}

bool B()
{
   .....
}

bool C()
{

 .....
}

今、他のいくつかの機能で、メインで言う:

int main()
{
  bool (*choice) ();

  // now if there is if-else statement for making "choice" to 
  // point at a particular function then proceed as following

  if ( x == 1 )
   choice = A;

  else if ( x == 2 )
   choice = B;


  else
   choice = C;

if(choice())
 printf("Success\n");

else
 printf("Failure\n");

.........
  .........
  }

これは関数ポインタの1つの例であることを忘れないでください。他にもいくつかの方法があり、関数ポインターを明確に学ぶ必要があります。

35
Abhineet

次のように関数ポインターを宣言します。

bool (*f)();
f = A;
f();
20

あなたの質問はすでに十分に回答されていると思いますが、関数ポインタが与えられていることを明示的に指摘することは有用かもしれません

void (*pf)(int foo, int bar);

2つの呼び出し

pf(1, 0);
(*pf)(1, 0);

定義上、あらゆる点で完全に同等です。どちらを使用するかはあなた次第ですが、一貫性を保つのは良い考えです。長い間、(*pf)(1, 0)を好んでいました。なぜなら、pfのタイプをよりよく反映しているように思えたからですが、ここ数年でpf(1, 0)に切り替えました。

15
Dale Hagglund

最初に、voidを取り、voidを返す関数ポインタ配列を定義します。関数がvoidを取得してvoidを返すと仮定します。

typedef void (*func_ptr)(void);

現在、これを使用して、そのような関数の関数ポインター変数を作成できます。以下のように:

func_ptr array_of_fun_ptr[3];

関数のアドレスを3つの変数に保存します。

array_of_fun_ptr[0]= &A;
array_of_fun_ptr[1]= &B;
array_of_fun_ptr[2]= &C;

以下のように、関数ポインターを使用してこれらの関数を呼び出すことができます。

some_a=(*(array_of_fun_ptr[0]))();
some_b=(*(array_of_fun_ptr[1]))();
some_c=(*(array_of_fun_ptr[2]))();
14
Vijay

次のように関数ポインターを宣言できます。

bool (funptr*)();

これは、何も取らずboolを返す関数への関数ポインタを宣言していると言います。

次の課題:

funptr = A;

関数ポインターを使用して関数を呼び出すには:

funptr();
6
codaddict
bool (*FuncPtr)()

FuncPtr = A;
FuncPtr();

これらの関数の1つを条件付きで呼び出す場合は、 関数ポインターの配列 の使用を検討する必要があります。この場合、A、B、およびCを指す3つの要素があり、AのfuncArray0など、配列のインデックスに応じて1つを呼び出します。

4
Firas Assaad
bool (*fptr)();

int main(void)
{
  ...
  ...
  printf("Enter your choice");
  scanf("%d",&a);
  switch(a)
{
  case 0:
         fptr = A;
         break;
  case 1:
         fptr = B;
         break;
  case 2:
         fptr = C;
         break;
  case 3:
          break;
}
(*fptr)();
return 0;
}

あなたの選択はaに保存されます;それに応じて、関数は関数ポインターに割り当てられます。最後に、選択に応じて、目的の結果を返すためにまったく同じ関数が呼び出されます。

2
wrapperm

それを読む最良の方法は「時計回り/スパイラルルール」です

デビッド・アンダーソン

http://c-faq.com/decl/spiral.anderson.html

2
Vaysage

あなたが言うときは注意してください:

_bool (*a)();
_

aを返す関数へのポインタで、指定されていない数のパラメータをとる」タイプのboolを宣言しています。 boolが定義されていると仮定すると(C99を使用していて_stdbool.h_を含んでいるか、typedefである可能性があります)、これは必要な場合とそうでない場合があります。

ここでの問題は、aが正しい値に割り当てられているかどうかをコンパイラがチェックする方法がないことです。関数宣言にも同じ問題が存在します。 A()B()、およびC()はすべて、「boolを返し、指定されていない数のパラメーターを受け取る」関数として宣言されます。

あるかもしれない問題の種類を見るために、プログラムを書きましょう:

_#include <stdio.h>

int test_zero(void)
{
    return 42;
}

static int test_one(char *data)
{
    return printf("%s\n", data);
}

int main(void)
{
    /* a is of type "pointer to function returning int
       and taking unspecified number of parameters */
    int (*a)();

    /* b is of type "pointer to function returning int
       and taking no parameters */
    int (*b)(void);

    /* This is OK */
    a = test_zero;
    printf("a: %d\n", a());

    a = test_one; /* OK, since compiler doesn't check the parameters */
    printf("a: %d\n", a()); /* oops, wrong number of args */

    /* This is OK too */
    b = test_zero;
    printf("b: %d\n", b());

    /* The compiler now does type checking, and sees that the
       assignment is wrong, so it can warn us */
    b = test_one;
    printf("b: %d\n", b()); /* Wrong again */

    return 0;
}
_

上記をgccでコンパイルすると、次のようになります。

警告:互換性のないポインタ型からの割り当て

_b = test_one;_行については、これで良いです。 aへの対応する割り当てに対する警告はありません。

したがって、次のように関数を宣言する必要があります。

_bool A(void);
bool B(void);
bool C(void);
_

そして、関数を保持する変数は次のように宣言する必要があります。

_bool (*choice)(void);
_
2
Alok Singhal

次のような複雑な定義に関するヘルプが必要な場合:

double (*(*pf)())[3][4];

私の右左のルールをご覧ください こちら

1
Jack

少し異なるアプローチ:

bool A() {...}
bool B() {...}
bool C() {...}

int main(void)
{
  /**
   * Declare an array of pointers to functions returning bool
   * and initialize with A, B, and C
   */
  bool (*farr[])() = {A, B, C};
  ...
  /**
   * Call A, B, or C based on the value of i
   * (assumes i is in range of array)
   */
  if (farr[i]()) // or (*farr[i])()
  {
    ...
  }
  ...
}
1
John Bode

次のように、関数の特定のシグネチャに対して関数ポインター変数を宣言します。

bool (* fnptr)();

次のいずれかの機能を割り当てることができます。

fnptr = A;

そしてあなたはそれを呼び出すことができます:

bool result = fnptr();

Typedefを使用して、必要な個別の関数シグネチャごとに型を定義することを検討できます。これにより、コードの読み取りと保守が容易になります。つまり、引数なしでboolを返す関数のシグネチャの場合、これは次のようになります。

typdef bool (* BoolFn)();

そして、次のように使用して、この型の関数ポインタ変数を宣言できます。

BoolFn fnptr;
1
x4u

関数ポインタを介して関数を呼び出す

float add(int , float),result;
int main()
{
 float (*fp)(int,float);
 float result;
 fp=add;
 result=add(5,10.9);      // Normal calling
 printf("%f\n\n",result);

 result=(*fp)(5,10.9);    //calling via function Pointer
 printf("%f\n\n",result);

 result=(fp)(5,10.9);    //calling via function Pointer,Indirection Operator can Be 
 omitted
 printf("%f",result);
 getch();
 }

float add(int a,float b)
{
return a+b;
}

出力

15.90000
15.90000
15.90000
0
Suraj Verma
//Declare the pointer and asign it to the function
bool (*pFunc)() = A;
//Call the function A
pFunc();
//Call function B
pFunc = B;
pFunc();
//Call function C
pFunc = C;
pFunc();
0
Khelben

これは十分に回答されていますが、これは便利な場合があります: The Function Pointer Tutorials 。これは、5つの章に分かれた主題の真に包括的な治療です!

0
Clifford

私は通常typedefを使用してそれを行いますが、関数ポインターをあまり頻繁に使用する必要がない場合は、やりすぎかもしれません。

//assuming bool is available (where I come from it is an enum)

typedef bool (*pmyfun_t)();

pmyfun_t pMyFun;

pMyFun=A; //pMyFun=&A is actually same

pMyFun();
0
Sint