C言語で関数をパラメータとして渡す方法

c function pointers syntax parameters


パラメータで渡された関数を、データの集合に対して実行する関数を作りたい。C言語で関数をパラメータとして渡すにはどうすればいいですか?




Answer 1 Niyaz


Declaration

関数のパラメータを取る関数のプロトタイプは以下のようになります。

void func ( void (*f)(int) );

これは、パラメーター f が、戻り値の型が void で、単一の int パラメーターを取る関数へのポインターになることを示しています。次の関数( print )は、適切な型であるため、パラメーターとして func に渡すことができる関数の例です。

void print ( int x ) {
  printf("%d\n", x);
}

関数呼び出し

関数パラメータを指定して関数を呼び出す場合、渡される値は関数へのポインタでなければなりません。これには関数名(括弧なし)を使用してください。

func(print);

func を呼び出して、それにprint関数を渡します。

関数本体

他のパラメーターと同様に、 func は関数の本文でパラメーターの名前を使用してパラメーターの値にアクセスできるようになりました。レッツはそれを言う func が、それは数字0-4に渡される関数を適用します。最初に、printを直接呼び出す場合のループは次のようになります。

for ( int ctr = 0 ; ctr < 5 ; ctr++ ) {
  print(ctr);
}

以来 func のパラメータ宣言は、その言う f は所望の機能へのポインタの名前で、我々は、場合ことを最初に思い出す f がポインタである、その後 *f は事ある f (すなわち、機能へのポイント print この場合)。その結果、上記のループ内のすべてのprintを *f に置き換えるだけです。

void func ( void (*f)(int) ) {
  for ( int ctr = 0 ; ctr < 5 ; ctr++ ) {
    (*f)(ctr);
  }
}

Source




Answer 2 roo


この質問はすでに関数ポインタの定義についての答えを持っていますが、関数ポインタは非常に厄介なものになる可能性があります。この不愉快さを避けるためには、関数ポインタをより読みやすいものに型定義することをお勧めします。例えば、以下のようになります。

typedef void (*functiontype)();

void を返し、引数を取らない関数を宣言します。この型への関数ポインタを作成するには、以下のようにします。

void dosomething() { }

functiontype func = &dosomething;
func();

int を返して char を受け取る関数の場合は、次のようにします。

typedef int (*functiontype2)(char);

と、それを使用するために

int dosomethingwithchar(char a) { return 1; }

functiontype2 func2 = &dosomethingwithchar
int result = func2('a');

関数ポインタを読みやすい型に変換するのに役立つライブラリがあります。ブースト機能のライブラリは素晴らしいですし、努力の価値があります!

boost::function<int (char a)> functiontype2;

は、上の方に比べれば、とても素敵です。




Answer 3 Richard


C ++ 11以降では、関数ライブラリを使用して、これを簡潔かつ一般的な方法で行うことができます。構文は、例えば、

std::function<bool (int)>

ここで bool は、最初の引数が int 型である1つの引数を持つ関数の戻り型です。

以下にプログラム例を載せておきます。

// g++ test.cpp --std=c++11
#include <functional>

double Combiner(double a, double b, std::function<double (double,double)> func){
  return func(a,b);
}

double Add(double a, double b){
  return a+b;
}

double Mult(double a, double b){
  return a*b;
}

int main(){
  Combiner(12,13,Add);
  Combiner(12,13,Mult);
}

しかし、テンプレート機能を使った方が便利な場合もあります。

// g++ test.cpp --std=c++11

template<class T>
double Combiner(double a, double b, T func){
  return func(a,b);
}

double Add(double a, double b){
  return a+b;
}

double Mult(double a, double b){
  return a*b;
}

int main(){
  Combiner(12,13,Add);
  Combiner(12,13,Mult);
}



Answer 4 Yogeesh H T


以下に示すように、関数のアドレスをパラメーターとして別の関数に渡します

#include <stdio.h>

void print();
void execute(void());

int main()
{
    execute(print); // sends address of print
    return 0;
}

void print()
{
    printf("Hello!");
}

void execute(void f()) // receive address of print
{
    f();
}

また、関数ポインタを使用して関数をパラメータとして渡すことができます

#include <stdio.h>

void print();
void execute(void (*f)());

int main()
{
    execute(&print); // sends address of print
    return 0;
}

void print()
{
    printf("Hello!");
}

void execute(void (*f)()) // receive address of print
{
    f();
}



Answer 5 doppelheathen


ISO C11 6.7.6.3p8に従って、関数を関数ポインターとして「渡す」ことができます。「''関数の戻り値の型 ''としてのパラメーターの宣言は、 6.3のように、''関数の戻り値の型へのポインター ''に調整されます。 .2.1。 " たとえば、これ:

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

がこれに相当します。

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