所以今天我认为(第一次是公认的)int foo()
实际上与int foo(void)
不同,因为第一个允许任何数量的输入和第二个一个允许零。
int foo()
是否会忽略任何给定的输入?如果是这样,那么允许这种形式的功能有什么意义呢?如果没有,你怎么能访问它们,这与拥有可变参数列表(例如int foo (int argc, ...)
之类的东西)有何不同?
答案 0 :(得分:4)
理解这一点的关键是理解调用堆栈。在C语言中调用函数时(使用标准x86 ABI - 其他平台可能不同),调用者在调用被调用者之前将所有参数以相反的顺序推送到堆栈上。然后,被调用者可以根据需要读取尽可能多的参数。如果你使用foo(void),显然你不会阅读任何内容。如果你使用foo(int),你将能够在当前帧下面的堆栈中读取一个单词。
使用foo()(没有指定args)意味着编译器不会检查传递给foo的参数。什么都可以;没有合同。如果foo有两个不同的实现,它们使用不同类型作为参数,这可能很有用,我希望能够以编程方式将它们切换出来。 (在汇编程序中编写函数时,它有时也很有用,你可以自己处理堆栈和参数。)但请记住,编译器不会为你做任何类型检查,所以你必须非常小心。
这与foo(int,...)不同,因为在这种情况下,该函数实际上有一种方法可以访问所有参数(使用varargs)。没有理由用foo()实际定义函数,因为它基本上等同于foo(void)。 foo()仅对声明有用。
答案 1 :(得分:1)
首先,取int foo()
。此表单是一个函数声明,它不提供原型 - 也就是说,它不指定其参数的数量和类型。它是一种古老的函数声明形式 - 它是函数最初是在ANSI-C之前声明的。但是这样的函数有一个固定数量和类型的参数 - 只是声明不是告诉编译器它是什么,所以你有责任在你调用函数的地方正确。你用这样的参数声明这样一个函数:
int foo(a, b)
int a;
char *b;
{
return a + strlen(b);
}
这种形式的功能声明现已过时。
int foo(void)
是一个提供原型的现代宣言;它声明了一个不带参数的函数。 int foo(int argc, ...)
也提供原型;它声明了一个具有一个固定整数参数和一个变量参数列表的函数。
答案 2 :(得分:0)
在标准符合C中,如果函数不接受任何参数,则必须使用int foo(void)
。
我认为当你将参数传递给带有空括号的函数时,它依赖于编译器会发生什么。但我认为没有办法访问这些参数。
至于main,唯一符合标准(纯c)的方法是int main(void)
或int main(int argc, char **argv)
(或char * argv [],它们是相同的)。
答案 3 :(得分:0)
嗯,在C ++中,两种形式是等价的,它们都声明了一个不带参数的函数。如果您尝试调用该函数并传入参数,则编译将发出错误。
另一方面,C和Objective-C都以不同的方式对待这两种形式。在这些语言中,第一个表单声明一个函数,该函数接受未知数量的参数,而第二个表单声明一个根本不接受任何参数的函数。因此,在C中,以下是有效的代码:
int foo() {
return 5;
}
int main() {
return foo(1, 2, 3);
}
编译器没有抱怨,代码运行正常(C ++编译器会在同一代码上出错)。
通常你想要的C和Objective-C是使用第二种形式并包含显式的void来表明该函数不应该带参数。但是,在C ++中使用第一种形式更为常见,因为它等效且更短。