C中的int foo(int argc,…)vs int foo()vs int foo(void)

所以今天我认为(第一次不可否认) int foo()实际上与int foo(void)不同,因为第一个允许任意数量的输入而第二个允许

int foo()是否只是忽略任何给定的输入? 如果是这样,那么允许这种forms的function有什么意义呢? 如果没有,你怎么能访问它们,这与变量参数列表有什么不同(例如int foo (int argc, ...) )?

理解这一点的关键是理解调用堆栈。 当您在C中调用函数时(使用标准x86 ABI – 其他平台可能不同),会发生的情况是调用者在调用被调用者之前将所有参数以相反的顺序推送到堆栈上。 然后,被调用者可以根据需要读取尽可能多的参数。 如果你使用foo(void),显然你不会阅读任何内容。 如果你使用foo(int),你将能够在当前帧下面的堆栈中读取一个单词。

使用foo()(没有指定args)意味着编译器不会检查你传递给foo的参数。 什么都可以; 没有合同。 如果foo有两个不同的实现,它们使用不同类型作为参数,这可能很有用,我希望能够以编程方式将它们切换出来。 (在汇编程序中编写函数时,它有时也很有用,你可以自己处理堆栈和参数。)但请记住,编译器不会为你做任何类型检查,所以你必须非常小心。

这与foo(int,…)不同,因为在这种情况下,函数实际上有一种方法来访问所有参数(使用varargs)。 没有理由用foo()实际定义函数,因为它基本上等同于foo(void)。 foo()仅对声明有用。

首先,采用int foo() 。 此表单是一个不提供原型的函数声明 – 也就是说,它没有指定其参数的数量和类型。 它是一种古老的函数声明forms – 它是函数最初在ANSI-C之前声明的方式。但是这样的函数确实一个固定数量和类型的参数 – 它只是声明不告诉编译器它是什么,因此,您有责任在调用该函数的地方正确使用它。 你用这样的参数声明这样一个函数:

 int foo(a, b) int a; char *b; { return a + strlen(b); } 

这种forms的function声明现在已经过时了。

int foo(void)是一个提供原型的现代声明; 它声明了一个不带参数的函数。 int foo(int argc, ...)也提供了原型; 它声明了一个具有一个固定整数参数和一个变量参数列表的函数。

在标准符合C中,如果函数不接受任何参数,则必须使用int foo(void)

我想当你将参数传递给带有空括号的函数时,它依赖于编译器会发生什么。 但我认为没有办法访问这些参数。

至于main,唯一的标准符合(纯c)方式来编写它们是int main(void)int main(int argc, char **argv) (或char * argv [],它们是相同的)。

好吧,在C ++中,两种forms是等价的,它们都声明了一个不带参数的函数。 如果您尝试调用该函数并传入参数,则编译将给出错误。

另一方面,C和Objective-C都以不同的方式对待这两种forms。 在这些语言中,第一种forms声明了一个接受未知数量参数的函数,而第二种forms声明了一个根本不接受任何参数的函数。 所以,在C中,以下是有效的代码:

 int foo() { return 5; } int main() { return foo(1, 2, 3); } 

编译器没有抱怨,代码运行正常(C ++编译器会在同一代码上给出错误)。

通常你在C和Objective-C中想要的是使用第二种forms并包含显式的void来表明该函数不应该带参数。 但是,在C ++中使用第一种forms更为常见,因为它等效且更短。