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

C語言 GCC 嵌入式時代 2019-09-12
"

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

"

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

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

void fun(void),為什麼還要多此一舉的寫上 void 呢?

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

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

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

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

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

"

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

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

void fun(void),為什麼還要多此一舉的寫上 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 <stdio.h>
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語言初學者常會在前輩留下的項目,或者一些開源項目中看到以 void 作為參數的函數,例如 void fun(void),雖然我們都明白在C語言中,“void”表示空,但是按理說,如果函數不需要參數,直接空著就行:void fun(),為什麼還要多此一舉的寫上 void 呢?

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

void fun(void),為什麼還要多此一舉的寫上 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 <stdio.h>
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); //非法\t
"

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

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

void fun(void),為什麼還要多此一舉的寫上 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 <stdio.h>
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); //非法\t
C語言定義無參數的函數時,f()和f(void)有什麼區別?

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

標識符列表方式定義函數

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

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

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

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

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

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

void fun(void),為什麼還要多此一舉的寫上 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 <stdio.h>
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); //非法\t
C語言定義無參數的函數時,f()和f(void)有什麼區別?

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

標識符列表方式定義函數

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

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

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

一般不推薦使用“標識符列表”方式定義C語言函數,這種方式在以前比較流行,如今有一些存在於許多歷史遺留的代碼中。
C語言定義無參數的函數時,f()和f(void)有什麼區別?

一般不推薦使用“標識符列表”方式定義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語言初學者常會在前輩留下的項目,或者一些開源項目中看到以 void 作為參數的函數,例如 void fun(void),雖然我們都明白在C語言中,“void”表示空,但是按理說,如果函數不需要參數,直接空著就行:void fun(),為什麼還要多此一舉的寫上 void 呢?

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

void fun(void),為什麼還要多此一舉的寫上 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 <stdio.h>
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); //非法\t
C語言定義無參數的函數時,f()和f(void)有什麼區別?

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

標識符列表方式定義函數

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

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

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

一般不推薦使用“標識符列表”方式定義C語言函數,這種方式在以前比較流行,如今有一些存在於許多歷史遺留的代碼中。
C語言定義無參數的函數時,f()和f(void)有什麼區別?

一般不推薦使用“標識符列表”方式定義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語言定義無參數的函數時,f()和f(void)有什麼區別?

點個贊再走吧

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

未經許可,禁止轉載。

"

相關推薦

推薦中...