C语言函数void fun()和 void fun(void)有什么区别?

相信C语言初学者常会在前辈留下的项目,或者一些开源项目中看到以 void 作为参数的函数,例如 void fun(void),虽然我们都明白在C语言中,“void”表示空,但是按理说,如果函数不需要参数,直接空着就行:void fun(),为什么还要多此一举的写上 void 呢?

C语言函数参数的定义方式

大多数C语言教程在谈到自定义函数时,一般都将函数的“参数类型列表”放在“()”中,例如:

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

C语言没有理由将“无参数函数”作为特例处理,因此从“通用性”来看,定义C语言函数时,“()”内应该始终有“参数类型列表”,如果函数不需要使用参数,应该指定为 void,而不是空着。

但是在C语言程序开发中,void fun(); 这种定义函数的方式又的确是可行的,难道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语言代码,得到如下输出:

# 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语言函数时,“()”内必须指定参数类型——如果不需要参数,需要指定其为 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语言
添加新评论

icon_redface.gificon_idea.gificon_cool.gif2016kuk.gificon_mrgreen.gif2016shuai.gif2016tp.gif2016db.gif2016ch.gificon_razz.gif2016zj.gificon_sad.gificon_cry.gif2016zhh.gificon_question.gif2016jk.gif2016bs.gificon_lol.gif2016qiao.gificon_surprised.gif2016fendou.gif2016ll.gif