C語言定義無引數的函式時,f()和f(void)有什麼區別?
相信C語言初學者常會在前輩留下的專案,或者一些開源專案中看到以 void 作為引數的函式,例如 void fun(void),雖然我們都明白在C語言中,“void”表示空,但是按理說,如果函式不需要引數,直接空著就行:void fun(),為什麼還要多此一舉的寫上 void 呢?
void fun(void),為什麼還要多此一舉的
C語言函式引數的定義方式
大多數C語言教程在談到自定義函式時,一般都將函式的“引數型別列表”放在“()”中,例如:
void f(int a, float b){ 。。。}
C語言沒有理由將“無引數函式”作為特例處理,因此從“通用性”來看,定義C語言函式時,“()”內應該始終有“引數型別列表”,如果函式不需要使用引數,應該指定為 void,而不是空著。
但是在C語言程式開發中,void fun(); 這種定義函式的方式又的確是可行的,難道C語言真的將“無引數函式”作為特例處理了嗎?
難道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語言程式碼
編譯並執行這段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); //非法
它限制了 fun() 函式不能接收任何引數
識別符號列表方式定義函式
現在我們已經知道,以引數型別列表方式定義C語言函式時,“()”內必須指定引數型別——如果不需要引數,需要指定其為 void。
因此,void fun(); 這種定義方式其實是以識別符號列表方式定義的,只不過引數的型別和數目被省去了,因此呼叫者在呼叫 fun() 函式時,必須事先知道引數型別和數目。
如果傳遞給函式的引數是任意的(這對於以“識別符號列表方式”定義的函式是允許的),那麼就可能導致函數出現不預期的行為。例如函式的堆疊可能會被破壞,因為編譯器並不限定傳遞的引數個數,函式在獲得控制權後可能會出現不同的記憶體佈局。
一般不推薦使用“識別符號列表”方式定義C語言函式,這種方式在以前比較流行,如今有一些存在於許多歷史遺留的程式碼中。
一般不推薦使用“識別符號列表”方式定義
引數型別列表方式定義函式
以引數型別列表方式定義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語言、linux等嵌入式開發,喜歡我的文章就關注一波吧,可以看到最新更新和之前的文章哦。
未經許可,禁止轉載。