[置顶] 泰晓 RISC-V 实验箱,配套 30+ 讲嵌入式 Linux 系统开发公开课
如果 main 函数的末尾没有 return 语句将会有什么影响
By Falcon of TinyLab.org Dec 09, 2019
背景简介
本文是前段在知乎回答的一个问题,觉得蛮重要的,重新编撰发布如下。
原问题为:
我是准大一,学计算机的,刚刚接触计算机,萌新求解答
问题的本质
回答这个问题其实只要理解一个东西就行了:
那就是带有返回值的函数请务必提供返回值,这个是基本约定也是编程习惯,如果大家都遵守,你不遵守,各种奇葩和头疼的后果就迟早会来,不管是 main 也好,其他函数也好。
所以,准大一这个时候一定要从现在开始养成习惯,遵守语言的基本约定。
main 的标准声明
main
的标准声明是什么?
int main(int argc, char *argv[])
很多同学写例子,也有这么写的?
void main(void) { }
实际上,完整的 main 声明还有第三个参数 env,这里不做展开。
C 语言各标准差异以及静态检测方法
这种可以用 -Wall
检查出来:
$ echo 'void main(void) {}' | gcc -Wall -x c - -
<stdin>:1:6: warning: return type of ‘main’ is not ‘int’ [-Wmain]
如果用 int
默认检查不出来 return value ,默认是兼容 c11 的 gnu11:
$ echo 'int main(void) {}' | gcc -Wall -x c - -
$ echo 'int main(void) {}' | gcc -Wall -std=gnu11 -x c - -
试了下,c99 之后都是没有提示问题。但是 c90 以及之前都提示需要加返回值:
$ echo 'int main(void) {}' | gcc -Wall -std=c90 -x c - -
<stdin>: In function ‘main’:
<stdin>:1:1: warning: control reaches end of non-void function [-Wreturn-type]
考虑到兼容性,建议务必养成写上的习惯。由于 main 稍微特殊些,c99 默认处理了,但是对于其他函数还是要自己加,不做处理的话,是有很大风险的。
对于 c99 以及之后的版本,对普通函数还是会做检查。 如果有的写,有的不写,不一致的话久而久之习惯就很难养成了。
$ echo 'int test(void) {}; int main(void) { test(); }' | gcc -Wall -std=c99 -x c - -
<stdin>: In function ‘test’:
<stdin>:1:1: warning: control reaches end of non-void function [-Wreturn-type]
由于人总会出错,所以,在编译的 cflags 里头,建议强制加上 -Wall -Werror
,在遇到这类错误是强制退出,而不仅仅是警告。当然,对于已经存在的项目,prove-in-use 的情况下,建议保留之前的默认配置选项,除非要确实投入很多精力去重构。
$ echo 'int main(void) {}' | gcc -Wall -Werror -std=c90 -x c - -
<stdin>: In function ‘main’:
<stdin>:1:1: error: control reaches end of non-void function [-Werror=return-type]
cc1: all warnings being treated as errors
关于返回值的含义
需要注意的是,默认情况下,没有错误,就是 return 0
,而不是 return 1
。
完整的模板:
int main(int argc, char *argv[])
{
return 0;
}
更多关于 main 和 C 函数入口的讨论,欢迎访问:GCC 编译的背后 以及 《360° 剖析 Linux ELF》视频课程。
上面多次提到了后果和风险,为什么?因为检查函数和程序返回值是一个最最基础的操作。如果不按常理返回正确的返回值,后果是,后续对该值的检查所做出的所有动作都可能不可预知。
这个值是怎么体现的呢?
$ echo -e 'int main(void){ return 0; }' | gcc -Wall -Werror -std=c99 -O0 -x c - -
$ ./a.out
$ echo $?
0
$ echo -e 'int main(void){ return 100; }' | gcc -Wall -Werror -std=c99 -O0 -x c - -
$ ./a.out
$ echo $?
100
比如说,在 Shell
编程中通常会在程序执行完,立即检查返回值,然后决定接下去做什么操作?
if [ $? -eq 0 ]; then echo 'Success'; else echo 'Failure'; fi
关于 Shell 的布尔操作,可以参考:Shell 编程范例之布尔运算。
猜你喜欢:
- 我要投稿:发表原创技术文章,收获福利、挚友与行业影响力
- 知识星球:独家 Linux 实战经验与技巧,订阅「Linux知识星球」
- 视频频道:泰晓学院,B 站,发布各类 Linux 视频课
- 开源小店:欢迎光临泰晓科技自营店,购物支持泰晓原创
- 技术交流:Linux 用户技术交流微信群,联系微信号:tinylab
支付宝打赏 ¥9.68元 | 微信打赏 ¥9.68元 | |
请作者喝杯咖啡吧 |