c/c++ 返回值问题
起因
今天在群里讨论了一个问题.还是很有意思的,是一个上线后发现的问题。C/C++返回值的问题.代码(主要是test函数代码)
#include <stdio.h>
#include <stdlib.h>
int test()
{
if (1 > 0) //注意这里===============
{
//模拟这里没有返回值
}
else
{
return 1;
}
}
int main(int argc, char* argv[])
{
int val = test();
printf("val=%d\n", val);
return 0;
}
看到上方的代码,我们心理存在有两个问题:
- 代码能编译成功吗?
- 如果编译成功,返回值是多少? 是0还是1???
至于返回值是0还是1,这个要看编译器(vs中cl,gcc)和生成多少位(32位和64位)返回值是不一样的.
打上断点,先看vs x86(32位),返回值是多少?返回的是0
x64(64位编译器): 返回的是0

用64位gcc编译时,返回值是1

C++中,如果分支没有返回值的话,也是编译运行的
#include <iostream>
using namespace std;
int test()
{
if (1 > 0)
{
}
else
{
return 1;
}
}
int main(int argc, char* argv[])
{
int val = test();
std::cout << "val=" << val << std::endl;
return 0;
}
这里就不展示结果,感兴趣的话,可以自己编译运行.
为什么要说c++呢? 是因为群里的群友刚开始说这个返回值问题是C++代码,我回的应该是历史遗留问题(从C语言继承的问题).推测是C++兼容C语言(号称百分比兼容),用这样的代码继续证明:
int main(int argc, char* argv[])
{
//不管c/c++都可以编译运行
//return 0;
}
主要是C语言设计的时候,是以性能和灵活著称的,拿数组越界来说,在C语言中交给程序员了,编译器不做安全验证(早期的编译),后面的编程语言在设计的时候,就是开始以安全指标.如Java在语言层面上干掉了指针.Rust也在避免野指针的存在.安全和性能是需要平衡的.所以在C#和Rust都可以使用指针(要先标记不安全).
其他语言 c#和Rust
分支上,如果存在没有返回值的情况,是无法编译通过的.c#编译提示:
Rust编译提示:
结论
在C/C++(其他语言最好也开启)中,在编译器中要开启把警告视为错误.这样能更早更及时的发现问题.
秋风
2020-11-11