C語言定義無引數的函式時,f()和f(void)有什麼區別?

相信C語言初學者常會在前輩留下的專案,或者一些開源專案中看到以 void 作為引數的函式,例如 void fun(void),雖然我們都明白在C語言中,“void”表示空,但是按理說,如果函式不需要引數,直接空著就行:void fun(),為什麼還要多此一舉的寫上 void 呢?

C語言定義無引數的函式時,f()和f(void)有什麼區別?

void fun(void),為什麼還要多此一舉的

C語言函式引數的定義方式

大多數C語言教程在談到自定義函式時,一般都將函式的“引數型別列表”放在“()”中,例如:

void f(int a, float b){ 。。。}

C語言沒有理由將“無引數函式”作為特例處理,因此從“通用性”來看,定義C語言函式時,“()”內應該始終有“引數型別列表”,如果函式不需要使用引數,應該指定為 void,而不是空著。

但是在C語言程式開發中,void fun(); 這種定義函式的方式又的確是可行的,難道C語言真的將“無引數函式”作為特例處理了嗎?

C語言定義無引數的函式時,f()和f(void)有什麼區別?

難道C語言真的將“無引數函式”作為特

其實不是的,在C語言中,定義函式時,指定引數還有另外一種方式(識別符號列表方式):

void f(a, b)

int a; float b;

{ 。。。}

以識別符號列表方式定義函式不常見,但的確是可用的,下面是一段完整的測試C語言程式碼,請看:

#include

void f(a, b)

int a; float b;

{

printf(“%d, %f\n”, a, b);

}

int main(){

f(); f(1); f(2, 3。14);

return 0;

}

C語言定義無引數的函式時,f()和f(void)有什麼區別?

C語言程式碼

編譯並執行這段C語言程式碼,得到如下輸出:

# gcc t。c -Wall

# 。/a。out

1, 0。000000

1, -inf

2, 3。140000

可見,以“識別符號列表方式”定義C語言函式,在呼叫時,函式的表現很像不定引數函式,未明確傳遞值的引數的值是未定義的。

另外,定義C語言函式時,識別符號列表可以省去,但是引數型別列表不可以。因此,void fun(); 這種定義函式的方式其實是“識別符號列表”被省去的一種特殊。

正如前面所討論的,以“識別符號列表方式”定義的C語言函式表現很像不定引數函式,因此 void fun(); 定義的函式,傳遞給其任意多的引數都是允許的:

void fun(){。。。}

fun();

fun(1,3,4); //合法

而 void fun(void); 這種指定引數型別列表的定義方式就不同了,它限制了 fun() 函式不能接收任何引數:

void fun(void){。。。}

fun();

fun(1,2,3); //非法

C語言定義無引數的函式時,f()和f(void)有什麼區別?

它限制了 fun() 函式不能接收任何引數

識別符號列表方式定義函式

現在我們已經知道,以引數型別列表方式定義C語言函式時,“()”內必須指定引數型別——如果不需要引數,需要指定其為 void。

因此,void fun(); 這種定義方式其實是以識別符號列表方式定義的,只不過引數的型別和數目被省去了,因此呼叫者在呼叫 fun() 函式時,必須事先知道引數型別和數目。

如果傳遞給函式的引數是任意的(這對於以“識別符號列表方式”定義的函式是允許的),那麼就可能導致函數出現不預期的行為。例如函式的堆疊可能會被破壞,因為編譯器並不限定傳遞的引數個數,函式在獲得控制權後可能會出現不同的記憶體佈局。

一般不推薦使用“識別符號列表”方式定義C語言函式,這種方式在以前比較流行,如今有一些存在於許多歷史遺留的程式碼中。

C語言定義無引數的函式時,f()和f(void)有什麼區別?

一般不推薦使用“識別符號列表”方式定義

引數型別列表方式定義函式

以引數型別列表方式定義C語言函式是今天的主流,這種方式更加安全,因為它嚴格限定呼叫者傳遞給函式的引數型別和個數。例如 void fun(void); 函式在被呼叫時,只能以無引數方式呼叫 fun()。

另外,以引數型別列表方式定義的C語言函式,編譯器能夠準確知道引數的資料型別,因此函式可以對接收到的引數做隱式的型別轉換,還可以對引數做一些型別提升(即所謂的預設引數提升),例如 char 型別提升為 int。

最後

順便說一下,如果某個原始檔中出現了省略的識別符號列表方式定義的函式,和引數列表方式定義的函式,那麼C語言原型將以引數列表方式定義的為準,請看下面這段C語言程式碼:

void f();

void f(int a){ 。。。}

原因也是簡單的,void f(); 定義的函式 f() 可以接收任意多的引數,而 void f(int a); 定義的函式 f() 只能接收一個 int 型的引數,編譯器為了不違背二者,只好讓函式 f() 只接受一個 int 型引數了。

C語言定義無引數的函式時,f()和f(void)有什麼區別?

點個贊再走吧

歡迎在評論區一起討論,質疑。文章都是手打原創,每天最淺顯的介紹C語言、linux等嵌入式開發,喜歡我的文章就關注一波吧,可以看到最新更新和之前的文章哦。

未經許可,禁止轉載。