main 是一个函数,就像其他函数一样。几乎。无论如何,作为一个函数,它被其他一些代码(启动代码)调用。通常(阅读:几乎总是)int main() 是正确的,但实际上什么是真正正确的取决于您正在使用的平台。因为,如上所述,主函数可以由根本不传入任何参数的启动代码调用,并且在特定寄存器中不期望返回值(因此void main(void) 是正确的)。
int main() 是正确的,因为通常启动代码需要一个返回值,并传入两个参数。通过说int main(void),您是在说 main 根本不接受任何参数,在大多数情况下这是错误的。对于(),你说有参数(一、二、三,你不在乎),但你对它们不感兴趣,所以你对说它们是什么以及它们是哪种类型不感兴趣。
正如我在代码中看到的那样,当您忽略传递的 int argc, char **argv 参数时,“正常”环境(没有嵌入式设备或其他可以以不同方式调用 main 的“奇怪”环境)的最常用原型是 int main()。 (GCC 抱怨,因为我们使用的是适合环境的 gcc 版本;在启动代码不传递任何参数且不期望返回值的环境之一使用跨 GCC 版本对其进行测试)
编辑
只是为了善待持怀疑态度的人;在调用 main 函数的环境中,使用两个参数,如下
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;
}
说 A 没有错误,而 B 说 too many arguments to function ‘func2’,用 gcc -std=c99 -pedantic 编译。将 int main(void) 更改为 int main() 没有任何区别,也没有警告。
在其他环境中(我现在无法进行实际测试),void main(void) 没问题,而在这种情况下它会发出警告。警告不仅仅是因为标准,而只是因为在使用的环境中 main 的原型不匹配。标准似乎允许 main 的任何其他“配置”。
在 OP 情况下,考虑到“正常”环境(例如 GNU/Linux 之类的操作系统),其中两个 args 被传递给 main,并且预期返回值,int main() 更可取(参数被推送无论您是否说int main(void),启动代码的堆栈,所以int main()对我来说更有意义)
编辑
还有一个注意事项,总是给持怀疑态度的人。正如已经证明的那样,B 引发了一个错误,因为我说过它是int func2(void),但我称之为传递参数。然后,假设我们可以编译启动代码并链接它,就像任何其他代码一样。在某个地方,它会调用 main,就像
retval = main(argc, argv);
如果我们使用int main(void),编译器将停止并给出错误,因为启动代码(在此环境中)试图用两个参数调用 main。如果我们使用int main(),则不会发生任何事情,并且代码会正确编译。
所以,int main() 比int main(void)优越(在我们期望两个参数主要可能的环境中)
编辑
电话更可能是这样的
retval = main(_argc, _argv, environ);
在许多系统上,但这不会改变之前的演讲。
最终编辑
有没有人发现,在使用int main(void) 构建命令行工具(即在int argc, char ** 有意义的系统上)时,所选的编译器/链接器链接了一个启动代码,其中main 在没有参数的情况下被调用(无论调用约定是),而当使用int main(int argc, char **argv) 构建时,启动代码是不同的,实际上使用这两个参数调用main(即使main 本身不使用它们)?