2014-09-04 77 views
7

我有在C的語法如下麻煩:函數返回一個函數指針語法

float (*func(unsigned id))(float value) { 
    ... 
} 

我的理解是:

  • 這是一個調用函數的定義func
  • func接受一個類型爲unsigned的參數id
  • func返回一個指針,看起來像一個功能:float f(float value)

但我不明白爲什麼f(返回的函數指針)的返回值從參數列表分開。

另外,是:func(unsigned id)表達式評估爲某個指針?這就是爲什麼(*func(unsigned id))有效嗎?

有人可以逐步澄清此語法嗎?

+0

不值得加入作爲一個答案,但'cdecl'是一個命令行工具,將解釋這個給你。 – abligh 2014-11-23 12:48:42

回答

7

表達式func(id)返回一個指向一個函數的指針,該函數將float作爲參數並返回一個float。如果你有一個像功能

val = (*func(3))(3.14); // take the ptr returned by func(3) and call the function pointed to. 

float(*f)(float v); // pointer to a function 
float val;  

f = func(3);  // returns a pointer to a function 
val = (*f)(3.14); // calls the function pointed to with argument 3.14 

當然,你可以重寫了最後陳述

float fct1 (float v) { return 2.0f*v+3.1f; } 

你可以寫:

f = fct1;  // reassign the pointer to function f to the adress of fct1 

讓我們看看語法。 C11標準(草案N1570)在6.5.2.2中指出:第1點:「表示被調用函數的表達式」應該有類型指針指向函數「」,並且在第3點指出:「」後綴表達式後跟括號()包含一個可能爲空的逗號分隔的表達式列表是一個函數調用。「

這包括課程通常的情況:

val = fct1 (3.14); // fct1 is the function designator which adresses the function 
val = (*f) (3.14); // (*f) the dereferenced function pointer, so it addresses the function 

但下面也有效根據標準:

val = f(3.14); // This works as well, because f is a pointer to a function 
val = func(3)(3.14) // works also because func(3) is a pointer to a function 

但是第一個表達式是模糊的人類讀者,誰可能會認爲f作爲函數標識符,期望它在某處被定義。第二個也很不尋常。此外,早期版本的C沒有認出它們。 1978年的我的K & R版本需要形式(* f)()來調用函數指針。

最後一個語法註釋:如果您將f定義爲float *f (float);,它不會被理解爲指向函數的指針,而是被理解爲普通函數f的前向聲明並將指針返回爲float。爲什麼?因爲C precedence rules給予()*更高的優先級,這意味着編譯器將它理解爲(float *)(f(float))。這就是爲什麼需要明確的括號來表明(*f)是函數指針。

3
float (*func(unsigned id))(float value); 

是一個函數的聲明它接受一個無符號整型作爲參數指針返回到功能

到該指針指向(函數f)開一個浮子作爲參數返回浮動的功能。它的聲明是:

float f(float value); 

名稱func功能的

float (*func(unsigned id))(float value); 
     ^^^^ 

參數的函數func

float (*func(unsigned id))(float value); 
      ^^^^^^^^^^^ 

的的返回類型功能func

float (*func(unsigned id))(float value); 
    ^^^^^^^^     ^^^^^^^^^^^^^ 

如果函數有沒有參數它是這樣的:

float (*func())(float value); 

你問還有,就是:func(unsigned id)計算結果爲一些指針表達式?

沒有,它的名字func和參數的函數

(unsigned id)你開始看到什麼是現在func?它是一個返回指向另一個聲明函數的指針的函數。

我包含了代碼,您可以在其中明確地看到func函數的返回值與參考f函數相比的返回值。

#include <stdio.h> 

float f(float value); 
float (*func(unsigned id))(float value); 

int main() 
{ 

    /* print the address of the f function 
    * using the return value of function func 
    */ 
    printf("func return value: %p\n\n", func(2)); 




     /* print the address of the f function referencing 
     * its address 
     */ 
    printf("referencing f address: %p\n", &f); 

    return 0; 
} 

float (*func(unsigned id))(float value) 
{ 
    printf("Original function with argument id = %d called\n", id); 
    return f; 
} 

float f(float value) 
{ 
    printf("f function\n"); 
    return 0.1; 
} 
5

走這一步一步的幫助從C gibberish ↔ English

float (*func(unsigned id))(float value) { ... } 

先用「F」爲漂亮的網址替換「功能」有麻煩「功能」,然後取下參數名。

float (*f(unsigned))(float) 
// declare f as function (unsigned) returning pointer to function (float) returning float 

由此看來,f是函數聲明接受一個unsigned id。這是f(unsigned)的一部分。

它返回一個變量x就好像它被宣佈爲float (*x)(float)一樣。正如OP觀察到的那樣,前半部分與原始聲明中的下半部分是分開的。

建議實驗與該網站記住不要使用「功能」

例子:

int f2(unsigned); 
// declare f2 as function (unsigned) returning int 
int (*f3(unsigned)); 
// declare f3 as function (unsigned) returning pointer to int 
int (*f4)(unsigned); 
// declare f4 as pointer to function (unsigned) returning int 
int (*f5(unsigned))(char); 
// declare f5 as function (unsigned) returning pointer to function (char) returning int 
+0

非常好!所以你的'f3'就是我們都知道的擴展形式 - 'int * f3(unsigned)'? – 2014-09-04 22:42:14

+0

@barak manos是的 - 相同。增加了'f3',因爲它有助於解釋OP的'(* func(unsigned id))'。 – chux 2014-09-04 22:51:18

+0

明白了。永遠不必返回一個函數指針。我想這就是爲什麼語法看起來如此不可讀。無論如何,做這件事似乎毫無意義。我真的不能想到任何需要返回函數指針的場景......謝謝 – 2014-09-04 22:54:52