哪个更好:void foo()或void foo(void)? 使用void时,它看起来很丑且不一致,但有人告诉我它很好。这是真的吗?
编辑:我知道一些旧的编译器做奇怪的事情,但如果我只是使用GCC,是void foo()好吗?将foo (bar);然后被接受?
哪个更好:void foo()或void foo(void)? 使用void时,它看起来很丑且不一致,但有人告诉我它很好。这是真的吗?
编辑:我知道一些旧的编译器做奇怪的事情,但如果我只是使用GCC,是void foo()好吗?将foo (bar);然后被接受?
当前回答
在c语言中有两种指定参数的方法,一种是使用标识符列表,另一种是使用参数类型列表。标识符列表可以省略,但类型列表不能省略。所以,说一个函数在函数定义中没有参数,你可以用一个(省略的)标识符列表来做到这一点
void f() {
/* do something ... */
}
这是一个参数类型列表:
void f(void) {
/* do something ... */
}
如果在一个形参类型列表中只有一个形参类型是void(它必须没有名称),那么这意味着函数没有实参。但这两种定义函数的方法在声明内容方面存在差异。
标识符列表
第一个定义了函数接受特定数量的参数,但与所有使用标识符列表的函数声明一样,既没有传达计数,也没有传递所需参数的类型。因此,调用者必须事先准确地知道类型和计数。因此,如果调用者在调用函数时给出一些参数,则该行为是未定义的。例如,堆栈可能被破坏,因为被调用的函数在获得控制权时期望不同的布局。
不建议在函数参数中使用标识符列表。它在过去被使用,并且仍然存在于许多生产代码中。由于这些参数提升,它们可能会导致严重的危险(如果提升的参数类型与函数定义的形参类型不匹配,则行为也未定义!),当然,它们也不太安全。所以对于没有形参的函数,无论在函数的声明还是定义中,都要使用void。
参数类型列表
第二个定义函数接受零参数,并与所有使用形参类型列表(称为原型)声明函数的情况一样进行通信。如果调用者调用函数并给它一些参数,这是一个错误,编译器会吐出一个适当的错误。
The second way of declaring a function has plenty of benefits. One of course is that amount and types of parameters are checked. Another difference is that because the compiler knows the parameter types, it can apply implicit conversions of the arguments to the type of the parameters. If no parameter type list is present, that can't be done, and arguments are converted to promoted types (that is called the default argument promotion). char will become int, for example, while float will become 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);
第一个使用标识符列表定义函数,而第二个则使用包含参数类型列表的声明为其提供原型。
其他回答
在c++中,main()和main(void)没有区别。
但在C语言中,main()将被调用时带有任意数量的参数。
例子:
main (){
main(10, "abc", 12.28);
// Works fine!
// It won't give the error. The code will compile successfully.
// (May cause a segmentation fault when run)
}
Main (void)将不带任何参数被调用。如果我们试图传递它,那么这最终会导致编译器错误。
例子:
main (void) {
main(10, "abc", 12.13);
// This throws "error: too many arguments to function ‘main’ "
}
除了语法上的差异,许多人还出于实际原因更喜欢使用void函数:
如果你正在使用搜索函数并想要找到函数的实现,你可以搜索function(void),它将返回原型以及实现。
如果省略void,则必须搜索function(),因此也将找到所有函数调用,从而使查找实际实现更加困难。
在c语言中有两种指定参数的方法,一种是使用标识符列表,另一种是使用参数类型列表。标识符列表可以省略,但类型列表不能省略。所以,说一个函数在函数定义中没有参数,你可以用一个(省略的)标识符列表来做到这一点
void f() {
/* do something ... */
}
这是一个参数类型列表:
void f(void) {
/* do something ... */
}
如果在一个形参类型列表中只有一个形参类型是void(它必须没有名称),那么这意味着函数没有实参。但这两种定义函数的方法在声明内容方面存在差异。
标识符列表
第一个定义了函数接受特定数量的参数,但与所有使用标识符列表的函数声明一样,既没有传达计数,也没有传递所需参数的类型。因此,调用者必须事先准确地知道类型和计数。因此,如果调用者在调用函数时给出一些参数,则该行为是未定义的。例如,堆栈可能被破坏,因为被调用的函数在获得控制权时期望不同的布局。
不建议在函数参数中使用标识符列表。它在过去被使用,并且仍然存在于许多生产代码中。由于这些参数提升,它们可能会导致严重的危险(如果提升的参数类型与函数定义的形参类型不匹配,则行为也未定义!),当然,它们也不太安全。所以对于没有形参的函数,无论在函数的声明还是定义中,都要使用void。
参数类型列表
第二个定义函数接受零参数,并与所有使用形参类型列表(称为原型)声明函数的情况一样进行通信。如果调用者调用函数并给它一些参数,这是一个错误,编译器会吐出一个适当的错误。
The second way of declaring a function has plenty of benefits. One of course is that amount and types of parameters are checked. Another difference is that because the compiler knows the parameter types, it can apply implicit conversions of the arguments to the type of the parameters. If no parameter type list is present, that can't be done, and arguments are converted to promoted types (that is called the default argument promotion). char will become int, for example, while float will become 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);
第一个使用标识符列表定义函数,而第二个则使用包含参数类型列表的声明为其提供原型。
void foo(void);
这是在C中说“无参数”的正确方式,在c++中也适用。
But:
void foo();
在C和c++中意味着不同的东西!在C语言中,它的意思是“可以接受任何数量的未知类型的参数”,在c++中,它的意思与foo(void)相同。
变量参数列表函数本质上是非类型安全的,应该尽可能避免使用。
Void foo(Void)更好,因为它显式地说:不允许有参数。
Void foo()意味着你可以(在某些编译器下)发送参数,至少如果这是你的函数的声明而不是它的定义。