前言
在C/C++程序中有时会见到采用诸如
void main()
等方式来声明主函数,很多人在主函数返回值的问题上也略显随意。经过查阅多版本的C、C++标准文档与相关书籍,我将我的结论与认识总结于此。不可避免地,其中可能包含我错误的认识,欢迎大家指正。main()函数的函数类型
关于
main()
的原型,C89/99/11以及C++98/03/11/14等标准给出的说法略有出入,尤其在早期标准中差异更为显著。然而,共同的,在任何一个版本的标准中,均未承认void main()
这种声明方式。首先可以得出结论:void main()
为错误写法,所有编译器都没有理由支持该种写法。
在K&R C与C89里,若函数没有显式声明返回类型,则默认是int
,因此在早期C程序中经常出现这样的主函数:
1 | main() |
这种写法在早期标准中是被认可的,main()
等价于int main()
。但是,C99标准不再支持函数的int
类型的默认设置,因此该写法被废止,新的编译器不再允许此类main函数。
在C99/11标准中,明确定义了对于标准的main函数的两个原型:
1 | int main(void) { /* ... */ } |
为了增强说服力,我在《C Primer Plus》(第六版)(该书以1999 ISO/ANSI作为标准)中找到了这样一段话:
如果浏览老版本的C代码,您将发现程序常常以:
main()
这种形式开始。C90标准勉强允许这种形式,但是C99标准不允许。因此即使您当前的编译器允许,也不要这么做。
您还将看到另一种形式:void main()
有些编译器允许这种形式,但是还没有任何标准考虑接受它。因而,编译器不必接受这种形式,并且许多编译器也不这样做。再者说,如果坚持使用标准形式,那么当您把程序从一个编译器移到另一个编译器时也不会有问题。
main()函数的形式参数
此部分C与C++略有差异
- C
int main()和int main(void)在C语言中是有区别的:
1 | int main() { /* ... */ } |
在C语言中参数列表为空(即不提供参数列表也不为void),表示不提供参数数量和参数类型信息:
1 |
|
因此在C中,main函数的参数部分应该以以下两种方式描述:
1 | int main(void) { /* ... */ } |
不应该写:
1 | int main() { /* ... */ } |
- C++
由于C和C++中对于函数参数列表的规则并不一致(C++中参数列表为空代表不接收任何参数)。所以C++中main的原型和ISO C也并不太一样。
在C++中,下面两种写法是完全等价的。
1 | int main() { /* ... */ } |
以上两种形式均符合标准。
main()函数的返回值
上文指出,main()
应以int类型定义,故需要返回一个int
类型的返回值到操作系统。
在早期标准中,主函数中的return 0;
是可以省略的,main()
最后如果没有返回值,则会自动return 0;
,但是记住,只有main函数是这样,其他函数不能省略return
。
自C99/C++98以来,主函数的返回值为强制,若漏掉了返回语句,大多数编译器会给出警告,但仍将编译程序。
return 0;
:一般用在主函数结束时,按照程序开发的一般惯例,表示成功完成本函数return -1;
:一般用在子函数结尾,按照程序开发的一般惯例,表示该函数失败
main()
必须要有返回值的原因是:在C和C++中使用return-statement都是将return的值作为参数来调用exit/std::exit来终止程序。
此外,返回值对于某些操作系统(包括DOS和UNIX)而言,具有实际的用途。
以Windows为例,编译以下程序:
1 | /* test.c */ |
在命令提示符下运行命令test && dir
,得到以下结果:
1 | D:\code>test && dir |
test.exe正常结束后执行dir
指令,输出了目录列表。
若将第4行返回值由0改为-1:
1 | return -1; |
再次执行test && dir
命令:
1 | D:\code>test && dir |
test.exe将-1返回给了操作系统,即程序异常结束,因此windows没有继续执行dir
打印目录列表。
总结一下,正常情况下main函数应以return 0;
结束,不能随意更改返回值。
结语
综上所述,一般情况下,C/C++程序的主函数都应该以如下方法编写:
1 | int main(void) // void在C++中可省,C不建议省 |
即使其他不标准的声明方法也许不会影响程序的正常编译、运行,但为了程序的可移植性与易维护性,我们应该养成良好的编码习惯,利人利己。
参考文献
[1] Stephen Prata 编著,《C Primer Plus》,人民邮电出版社,2005年,§2.2 §9.2 §B.5.
[2] Andrew Koenig 编著,《C陷阱与缺陷》,人民邮电出版社,2008年,§2.1 §7.1.
[3] Stephen Prata 编著,《C++ Primer Plus》,人民邮电出版社,2012年,§2.1 §2.4.
v1.4.4