2011-06-09 97 views
18

例如:在C中,作爲參數傳遞時,`&function`和`function`有什麼區別?

#include <stdio.h> 

typedef void (* proto_1)(); 
typedef void proto_2(); 

void my_function(int j){ 
    printf("hello from function. I got %d.\n",j); 
} 

void call_arg_1(proto_1 arg){ 
    arg(5); 
} 
void call_arg_2(proto_2 arg){ 
    arg(5); 
} 
void main(){ 
    call_arg_1(&my_function); 
    call_arg_1(my_function); 
    call_arg_2(&my_function); 
    call_arg_2(my_function); 
} 

運行此我得到如下:

> tcc -run try.c 
hello from function. I got 5. 
hello from function. I got 5. 
hello from function. I got 5. 
hello from function. I got 5. 

我的兩個問題是:

  • 有什麼用(* proto)和一個定義的函數原型之間的差異沒有定義?
  • 調用一個函數與參考運算符(&)和不帶?有什麼區別?
+1

我不認爲有區別。不張貼爲答案,因爲我不太確定。 – JAB 2011-06-09 13:20:44

+0

可能的重複[函數指針在C - 地址運算符「不必要的」](http://stackoverflow.com/questions/258422/function-pointers-in-c-address-operator-unnecessary) – outis 2012-01-24 03:48:57

回答

18

沒有區別。有關證據,請參閱C99 specification(第6.7.5.3.8節)。

「參數聲明爲'函數返回類型''應調整爲''指向 函數返回類型'',如6.3.2.1所示。」

+0

+1僅供參考 – groovingandi 2011-06-09 13:42:25

+0

感謝您的參考尼克! (順便說一句,它是第6.7節** 5 ** .3.8)所以它本質上是一種語言特例? – brice 2011-06-09 13:51:26

+0

@brice - 謝謝我編輯過。是一個特例。函數指針與其他語言的一致性更有意義,但我想他們爲了可讀性而添加了其他情況。 – 2011-06-09 13:53:59

7

有路過的arguement

&functionfunction沒有區別然而,有您的類型定義之間的差異。我不知道官方的解釋,即究竟是什麼區別,但是從我記得

typedef void (*name1)(void); 

typedef void(name2)(void); 

是不同的:

名1是一個指針,需要一個功能沒有參數並且什麼也不返回

name2是一個函數,它不需要參數並且不會返回任何內容

再次

typedef void (*pointer)(void); 
typedef void (function)(void); 

void foo(void){} 

int main() 
{ 
    pointer p; 
    function f; 

    p = foo; //compiles 
    p(); 

    f = foo; //does not compile 
    f(); 
} 

,我不是合適的人來解釋這種行爲的確切原因,但我相信,如果你看看標準,你會發現說明某處有

您可以通過編譯測試

+1

我想你可能已經感覺這一個來了:* ......當作爲論證傳遞時* - 其他方面有什麼區別呢? :-) – 2011-06-09 13:33:58

+0

呵呵:)不知道,但據我所知,完全一樣。爲什麼他們都存在?我不知道。我認爲它就像 int&const r; 和 int&r; C++ – 2011-06-09 13:39:43

+0

感謝您對typedefs的澄清。這是有道理的,並遵循通常的語義。 – brice 2011-06-09 13:57:48

5

功能和功能&沒有區別 - 它們都是地址。你可以看到這兩個:

function bar(); 

.... 
printf("addr bar is 0x%d\n", &bar); 
printf("bar is 0x%d\n", bar); 
+2

你的回答是正確的,但是「你可以看到......」是錯誤的。對於一個數組,'array'和'&array'不是相同的(它們有*非常不同的類型!),但是用printf打印它們的地址會顯示相同的東西(假設你正確地使用'%p'而不是'%d'並轉換爲'void *')。順便說一句,沒有辦法用'printf'打印函數指針,因爲C完全沒有從函數指針類型到void *或任何整數類型的轉換。 – 2011-06-09 13:34:55

+0

聲明「沒有辦法打印函數指針」是不正確的。你可以運行我粘貼在上面的代碼(我這樣做)。 – 2011-06-09 13:42:25

+2

該代碼通過將不匹配類型傳遞給'printf'來調用未定義的行爲。如果它符合您的預期,那就意味着您不幸運,即您的代碼中的錯誤未被發現。 – 2011-06-09 13:43:20

2

區別只是風格。您可以使用函數指針時具有相同的場景:

void func (void); 

...

void(*func_ptr)(void) = func; 

func_ptr(); // call func 
(*func_ptr)(); // call func 

printf("%d\n", ptr); 
printf("%d\n", *ptr); 

還有一些誰說,(* func_ptr)()語法是喜歡,使之清楚,函數調用是通過函數指針完成的。其他人則認爲*的風格更清晰。

像往常一樣,可能沒有科學研究證明任何一種形式都比另一種更好,所以只需選擇一種風格並堅持下去。

相關問題