我们为什么不在main中使用(void)?

时间:2010-07-01 09:13:04

标签: c

人们使用void main() /*empty parens ()*/

我被教导写void main(void)

任何想法有什么区别?

5 个答案:

答案 0 :(得分:37)

我不确定现在的标准是什么,但在传统的ANSI C中,使用空括号表示该函数可以使用任何个参数。另一方面声明void参数表示函数仅接受零参数。在这种情况下(以及许多其他情况),它实在无关紧要。

如果你想要严格,最好定义void参数。当然,main函数也可以定义为int main(int argc, const char* argv[]) - 这是完全有效的,但如果你不关心参数,通常是不必要的。

答案 1 :(得分:18)

来自C99标准:

  

5.1.2.2.1程序启动

     

程序启动时调用的函数名为main。实施宣布否   这个功能的原型。它应该使用返回类型int和no来定义   参数:

int main(void) { /* ... */ }
     

或有两个参数(这里称为argc和argv,但可能有任何名称   使用,因为它们是声明它们的函数的本地函数):

int main(int argc, char *argv[]) { /* ... */ }
     

或同等的;或者以其他一些实现定义的方式。

When main is defined without parameters, will argc and argv still be present on the stack?

答案 2 :(得分:5)

这些main()原型都是非标准的。

关于该问题的精确度可以在comp.lang.c faq:http://c-faq.com/decl/main.html

上找到

编辑:将“错误”更改为“非标准”,因为规范允许实现定义的原型。

答案 3 :(得分:2)

没有区别但通常main应该返回int。一些编译器会给你一个警告(至少GNU编译器 - gcc):

$ cat x.c
void main(void){}

$ gcc x.c
x.c: In function `main':
x.c:1: warning: return type of 'main' is not `int'

如上所述,main的原型是(根据标准):

int main(int argc, const char* argv[])

答案 4 :(得分:1)

main是一个函数,作为其他函数。几乎。无论如何,作为一个函数,它被一些其他代码(启动代码)调用。通常(读:几乎总是)int main()是正确的,但实际上正确的是什么取决于你正在使用它的平台。因为,如上所述,main函数可以由一个根本没有传递参数的启动代码调用,并且在特定寄存器中没有返回值(因此void main(void)是正确的)。

int main()是正确的,因为通常启动代码需要返回值,并传入两个参数。通过说int main(void)你说主要没有任何争论,在大多数情况下这是错误的。使用()你说有争论(一,二,三,你不在乎),但你对它们不感兴趣,所以你不想说它们是什么以及它们是什么类型。 / p>

正如我在代码中看到的,当你忽略传递的{{1}时,最常用的“正常”环境原型(没有嵌入式设备或其他主要可以被不同地调用的“奇怪”环境)是int main()参数。 (GCC抱怨因为我们正在使用适用于环境的gcc版本;使用交叉GCC版本测试它,其中一个环境是启动代码没有传递任何参数并期望没有返回值)

修改

善待持怀疑态度的人;在一个调用main函数的环境中,有两个参数,如下所示

int argc, char **argv

表示A没有错误,而B表示int func() { return 0; } int func2(void) { return 1; } int main(void) { int a; a = func(a, a); /* A */ a = func2(a); /* B */ return 0; } ,使用too many arguments to function ‘func2’编译。将gcc -std=c99 -pedantic更改为int main(void)没有任何区别,也没有任何警告。

在其他环境中(我现在无法进行实际测试),int main()没问题,而在这种情况下会引发警告。警告不是因为单独的标准,而是因为在使用环境中主要的原型不匹配。标准似乎允许任何其他“配置”为主。

在OP案例中,考虑到“正常”环境(如GNU / Linux等操作系统),其中两个args传递给main,并且返回值是预期的,void main(void)更可取(参数是无论你是否说int main(),你都会被启动代码推到堆栈上,所以int main(void)让我更有意义了)

修改

还有一个注意事项,总是对持怀疑态度的人。正如已经证明的那样,B引发了一个错误,因为我已经说它是int main(),但我称之为传递一个参数。然后,让我们假设我们可以编译启动代码并将其链接,就像任何其他代码一样。在某个地方,它将以类似

的方式调用main
int func2(void)

如果我们使用retval = main(argc, argv); ,编译器将停止,发出错误,因为启动代码(在此环境中)尝试使用两个参数调用main。如果我们使用int main(void)没有任何反应,代码会被正确编译。

所以,int main() 高级int main()(在我们期望有两个主要参数的环境中)

修改

调用更像是

int main(void)

在许多系统上,但这并没有改变以前的演讲。

最终修改

有没有人发现在使用retval = main(_argc, _argv, environ); 构建命令行工具(即在int argc, char **有意义的系统上)时,所选的编译器/链接器链接int main(void)所在的启动代码在没有参数的情况下调用(无论调用约定是什么),而在使用main构建时,启动代码是不同的,实际上使用这两个参数调用int main(int argc, char **argv)(即使main本身不使用它们?)