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;
}

看到上方的代码,我们心理存在有两个问题:

  1. 代码能编译成功吗?
  2. 如果编译成功,返回值是多少? 是0还是1???
实践出真知.还是先把代码编译一下.在VS2019是可以成功编译的.VS只是给个提示.

C语言中,如果分支没有返回值,是可以编译成功的.
至于返回值是0还是1,这个要看编译器(vs中cl,gcc)和生成多少位(32位和64位)返回值是不一样的.
打上断点,先看vs x86(32位),返回值是多少?返回的是0
32位编译,没有返回值的话,返回的值是1
x64(64位编译器): 返回的是0
64位编译,没有返回值的话,返回的值是0
用64位gcc编译时,返回值是1
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#编译提示:
在C#中,如果分支上存在没有返回值的情况,是无法编译成功的
Rust编译提示:
在Rust中,如果分支上存在没有返回值的情况,是无法编译成功的

结论

在C/C++(其他语言最好也开启)中,在编译器中要开启把警告视为错误.这样能更早更及时的发现问题.
在编译器中开启警告视为错误
秋风 2020-11-11