C语言中函数定义使用不带参数与使用void参数的区别
2018-11-16 本文已影响0人
zenny_chen
我们在C语言中定义函数时,往往将不带参数的函数声明为foo()
这种形式。尽管这种方式很直观,而且也跟其他类C语言声明的方式一样,然而这对于C语言而言不是真正能确定的不允许带任何参数的函数形式。下面我们来举一个简单例子进行呈现:
/// 声明不带参数的函数Hello
static void Hello()
{
}
static void Test()
{
// 这里对Hello的调用使用了两个int类型的实参,
// 这里仅仅报了“Too many arguments in call to 'Hello'”的警告
Hello(1, 2);
}
/// 这里对Hello进行重新声明,增加了两个int类型的参数,
/// 没有任何warning!
static void Hello(int, int);
int main(int argc, const char * argv[])
{
// 使用两个int类型的整数作为实参调用Hello,
// 没有任何warning
Hello(1, 2);
}
我们可以看到,上面所列出的代码在Clang编译器下可以正常编译和运行,尽管会有一些warning存在。
而如果我们把上述代码中的Hello声明为static void Hello(void)
会发生神马呢?我们看以下代码示例:
/// 声明不允许带任何参数的函数Hello
static void Hello(void)
{
}
static void Test()
{
// 这里对Hello的调用使用了两个int类型的实参,
// 报了“Too many arguments to function call, expected 0, have 2”的错误!
Hello(1, 2);
}
/// 这里对Hello进行重新声明,增加了两个int类型的参数,
/// 报了“Conflicting types for 'Hello'”的错误!
static void Hello(int, int);
int main(int argc, const char * argv[])
{
// 使用两个int类型的整数作为实参调用Hello,
// 报了“Too many arguments to function call, expected 0, have 2”的错误!
Hello(1, 2);
}
这样我们就能知道,foo()
这种形式不是说foo这个函数不允许带任何参数,而是指它带什么类型的参数,有多少个,是不确定的,而且可以对它作完整参数类型和个数的重新声明。而如果我们使用了foo(void)
这种形式,则就完全限定了foo的参数是不允许带任何参数的。如果对它重新声明,那么也不能用其他参数类型或任意增加其他参数。
在C语言中,void
用在除函数形参以外的地方的话可以作为一个类型(不完整类型)来使用,而如果作为函数形参类型的话,则表示真正意义上的“无”,并且甚至不允许含带任何表达式。我们下面举个例子:
/// 声明不允许带任何参数的函数Hello
static void Hello(void)
{
puts("Hello, world!");
}
/// 声明了不允许带任何参数的函数Test
static void Test(void)
{
/// 这里可以用return语句来返回同样具有void返回类型的Hello函数调用
return Hello();
}
int main(int argc, const char * argv[])
{
// 这种调用方式是错误的!调用Test函数时不允许传递任何参数,
// 这里会报:“Too many arguments to function call, expected 0, have 1”
Test(Hello());
}
因此,为了代码安全性考虑,我们以后在写C语言代码时,如果遇到要定义一个不带任何函数参数的时候,参数类型使用void
显式标明,而不是使用foo()
这种形式。而对于C++而言,foo()
与foo(void)
这两者是完全等同的,因为C++具有函数重载功能,所以从语言语法机制上就不会允许具有不同函数参数类型的两个同名函数作为一个函数实体存在。