C中有兩種指定參數的方法,一種是使用標識符列表,另一種是使用參數類型列表??梢允÷詷俗R符列表,但類型列表不能。因此,要說一個函數在函數定義中不接受參數,您可以使用一個(省略的)標識符列表來完成此操作。
void f() {
/* do something ... */}它有一個參數類型列表:
void f(void) {
/* do something ... */}如果在參數類型列表中,只有一個參數類型是無效的(它必須沒有名稱),那么這意味著函數沒有參數。但這兩種定義函數的方法在聲明什么方面有差異。
標識符列表
第一個定義函數接受特定數量的參數,但既沒有傳遞計數,也沒有傳遞所需內容的類型-就像使用標識符列表的所有函數聲明一樣。所以打電話的人必須事先準確地知道類型和計數。因此,如果調用者調用給它一些參數的函數,則行為是未定義的。例如,堆??赡軙p壞,因為被調用的函數在獲得控制時需要不同的布局。
不建議在函數參數中使用標識符列表。它在過去使用過,現在仍然存在于許多生產代碼中。由于這些參數提升,它們可能造成嚴重的危險(如果提升參數類型與函數定義的參數類型不匹配,行為也是未定義的!)當然也不太安全。所以,請始終使用void對于沒有參數的函數,只有在聲明和函數的定義中。
參數類型表
第二個函數定義為零參數,并與所有使用參數類型列表(稱為參數類型列表)聲明函數的情況進行通信。prototype..如果調用者調用該函數并給它提供一些參數,這就是一個錯誤,編譯器將產生一個適當的錯誤。
第二種聲明函數的方法有很多好處。當然,其中之一是檢查參數的數量和類型。另一個不同之處在于,因為編譯器知道參數類型,所以它可以將參數的隱式轉換應用到參數的類型。如果不存在參數類型列表,則不能這樣做,并且參數被轉換為提升類型(這稱為默認的參數提升)。char會變成int,例如,float會變成double.
函數的復合類型
順便說一句,如果一個文件同時包含一個省略的標識符列表和一個參數類型列表,那么參數類型列表“獲勝”。函數末尾的類型包含一個原型:
void f();void f(int a) {
printf("%d", a);}// f has now a prototype.這是因為這兩項聲明沒有任何矛盾之處。然而,第二個國家還有話要說。那就是有一個論點被接受了。同樣的情況也可以反向進行。
void f(a)
int a;{
printf("%d", a);}void f(int);前者使用標識符列表定義函數,而第二個則使用包含參數類型列表的聲明為其提供原型。