在接下来的几篇博文中,我将对c语言的main函数进行深入的剖析,分别从函数返回值,函数参数,以及函数的执行顺序对main函数作一总结。本文主要聊聊main函数的返回值。
main函数的返回值
main函数的返回值用于说明程序的退出状态。如果返回0,则代表程序正常退出。返回其它数字的含义则由系统决定。通常,返回非零代表程序异常退出。
void main()
有一些书上的,都使用了void main( ) ,其实这是错误的。C/C++ 中从来没有定义过void main( ) 。C++ 之父 Bjarne Stroustrup 在他的主页上的 FAQ 中明确地写着 “The definition void main( ) { /* … */ } is not and never has been C++, nor has it even been C.”
这可能是因为 在 C 和 C++ 中,不接收任何参数也不返回任何信息的函数原型为“void foo(void);”。可能正是因为这个,所以很多人都误认为如果不需要程序返回值时可以把main函数定义成void main(void) 。然而这是错误的!main 函数的返回值应该定义为 int 类型,C 和 C++ 标准中都是这样规定的。虽然在一些编译器中,void main() 可以通过编译,但并非所有编译器都支持 void main() ,因为标准中从来没有定义过 void main 。g++3.2 中如果 main 函数的返回值不是 int 类型,就根本通不过编译。而 gcc3.2 则会发出警告。所以,为了程序拥有很好的可移植性,一定要用 int main ()。
测试如下:
#include <stdio.h>
void main()
{
printf("Hello world\n");
return;
}
运行结果:g++ test.c
main()
那既然main函数只有一种返回值类型,那么是不是可以不写?规定:不明确标明返回值的,默认返回值为int,也就是说 main()等同于int main(),而不是等同于void main()。在C99中,标准要求编译器至少给 main() 这种用法来个警告,而在c98中这种写法是被允许的。但为了程序的规范性和可读性,还是应该明确的指出返回值的类型。
测试代码:
#include <stdio.h>
main()
{
printf("Hello world\n");
return 0;
}
运行结果:
C和C++的标准
在最新的 C99 标准中,只有以下两种定义方式是正确的:
int main( void )
int main( int argc, char *argv[] )
若不需要从命令行中获取参数,就使用int main(void) ;否则的话,就用int main( int argc, char *argv[] )。当然参数的传递还可以有其他的方式,在下一个文章中,会单独来讲。 main 函数的返回值类型必须是 int ,这样返回值才能传递给程序的调用者(如操作系统),等同于 exit(0),来判断函数的执行结果。
C++98 中定义了如下两种 main 函数的定义方式:
int main( )
int main( int argc, char *argv[] )
int main( ) 等同于 C99 中的 int main( void ) ;int main( int argc, char*argv[] ) 的用法也和C99 中定义的一样。同样,main函数的返回值类型也必须是int。
return 语句
如果 main 函数的最后没有写 return 语句的话,C99 和c++98都规定编译器要自动在生成的目标文件中加入return 0,表示程序正常退出。不过,建议你最好在main函数的最后加上return语句,虽然没有这个必要,但这是一个好的习惯。
在linux下我们可以使用shell命令:echo $? 查看函数的返回值。
#include <stdio.h>
int main()
{
printf("Hello world\n");
}
运行结果:
同时,需要说明的是return的返回值会进行 类型转换,比如:若return 1.2 ;会将其强制转换为1,即真正的返回值是1,同理,return ‘a’ ; 的话,真正的返回值就是97,;但是若return “abc”; 便会报警告,因为无法进行隐式类型转换。
测试main函数返回值的意义
前文说到,main函数如果返回0,则代表程序正常退出。通常,返回非零代表程序异常退出。在本文的最后,测试一下:
test.c
#include <stdio.h>
int main()
{
printf("c 语言\n");
return 11.1;
}
在终端执行如下:
➜ testSigpipe git:(master) ✗ vim test.c
➜ testSigpipe git:(master) ✗ gcc test.c
➜ testSigpipe git:(master) ✗ ./a.out && echo "hello world" #&&与运算,前面为真,才会执行后边的
c 语言
可以看出,操作系统认为main函数执行失败,因为main函数的返回值是11
➜ testSigpipe git:(master) ✗ ./a.out
➜ testSigpipe git:(master) ✗ echo $?
11
若将main函数中返回值该为0的话:
➜ testSigpipe git:(master) ✗ vim test.c
➜ testSigpipe git:(master) ✗ gcc test.c
➜ testSigpipe git:(master) ✗ ./a.out && echo "hello world" #hello
c 语言
hello world
可以看出,正如我们所期望的一样,main函数返回0,代表函数正常退出,执行成功;返回非0,代表函数出先异常,执行失败。
在下文中会对main函数的参数的使用做一总结。