2016-04-12 7 views
2

私は関数をパラメータとして持つことについて読んできました。特にCでは関数ポインタを使用しています。非線形方程式のゼロを計算するためにnewton raphsonメソッドを(簡単な方法で)実装したいとしましょう。C関数の代わりにポインタをパラメータとして使用するのはなぜですか?

double derivative(double f(double), double x) 
{ 
    double h = 1e-9; 
    return (f(x + h) - f(x))/h; 
} 

double newton_raphson(double f(double), double x0, double tol) 
{ 
    double xk, diff; 

    do 
    { 
     xk = x0 - f(x0)/derivative(f, x0); 
     diff = fabs(xk - x0); 
     x0 = xk; 
    } while (diff >= tol); 
    return xk; 
} 

したがって、微分の近似を計算するには、doubleを返し、引数としてdoubleをとる関数が必要です。他のパラメータが与えられている場合、関数の根を計算するのと同じです。私の質問は、なぜこれが関数ポインタを関数ポインタとして宣言するのと異なるのでしょうか?たとえば、入力パラメータfを単なる関数ではなく関数ポインタとして宣言する場合...

+1

として解釈されますた宣言のようなもので行きます機能は何ですか?例えば組立の視点から? –

+1

あなたのバージョンを試しましたか?それはコンパイルされますか? – dandan78

+1

パラメータ 'f'は関数ポインタです... – Cornstalks

答えて

7

パラメータfは、derivativenewton_raphsonの両方の関数へのポインタです。

double derivative(double f(double), double x) { ... } 

のみ、前者は立派に見える

double derivative(double (*f)(double), double x) { ... } 

とまったく同じです - あなたは括弧を省略することができたときには通常、あなたはおそらくそうする必要があります。結局のところ、両方とも同等です。

double ((((derivative)))(double (((*(f))))(double ((trouble))), double ((x)))) { ... } 

私は希望がIOCCCでのみ使用されることを願っています。あなたが宣言している場合


しかし、変数(ない関数パラメータ)を定義するには、

double f(double); 

だけの関数宣言である

double (*f)(double); 

として使用する必要があります。 (試作品を含む)


6.7.6.3関数宣言子C11ドラフトn1570のは言う:

パラメータの宣言 ' タイプ を返す関数は '''に調整しなければならないように' 関数へのポインタは、 タイプ ' 'を返します。6.3.2.1。

そして 6.9.1関数定義はさらに言うこと

[...]パラメータ型リストの6.7.6.3に記載されるように各パラメータのタイプを調整します。結果の型は完全型オブジェクト とする。

例2

は別の関数を渡すために、一つそして

int f(void); 
/* ... */ 
g(f); 

gかもしれないの定義を言うかもしれない:それは持っている次の例では、さらに

読み取り

void g(int (*funcp)(void)) 
{ 
     /* ... * 
     (*funcp)(); /* or funcp(); ... */ 
} 

または、等価的に、通常のデータ・ポインタと同様

void g(int func(void)) 
{ 
     /* ... */ 
     func(); /* or (*func)(); ... */ 
} 
+0

二重派生(double(* f)(double))として定義しても問題ありません... – dpalma

+2

はい、配列であるCの引数ではオブジェクトポインタに書き換えられ、関数ポインタは関数ポインタに書き換えられます。 –

0

、関数ポインタを引数として渡すことができ、また関数から戻すことができます。関数の名前は関数のアドレスを保持します。

私の質問は、なぜ関数ポインタを関数ポインタとして宣言するのと違うのですか?たとえば、入力パラメータfを単なる関数ではなく関数ポインタとして宣言する場合...

答えは両方の形式がコンパイラによって同じように扱われることです。 しかし、あなたのコードのreadibilityのために、あなたのコード例は、すなわち、

double derivative(double f(double), double x) { ... } 

でもCに、下記の関数定義がsame-

void foo(int a[]) // or int a[10] 
{ 
    ... 
} 

void foo(int *a) 
{ 
    ... 
} 
関連する問題