人们使用void main() /*empty parens ()*/
我被教导写void main(void)
任何想法有什么区别?
答案 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()
,但我称之为传递一个参数。然后,让我们假设我们可以编译启动代码并将其链接,就像任何其他代码一样。在某个地方,它将以类似
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
本身不使用它们?)