❤️ 痛心疾首,编译二十分钟后,竟然是因为这个warning出的错!❤️

一、问题描述

warning信息:warning: comparison between signed and unsigned integer expressio, 有符号/无符号不匹配
c++编译环境:centos7 + g++或者vs2015
c++代码举例

#include<iostream>
#include<bitset>
using namespace std;
int main()
{
	int x = -8;
	unsigned y = 7;

	if (x > y) {
		cout << x << endl;
	}
	else {
		cout << y << endl;
	}

	cout << "x      = " << x << endl;
	cout << "x 二进制 " << bitset<32>(x) << endl;
	cout << "y      = " << y << endl;
	cout << "y 二进制 " << bitset<32>(y) << endl;
	cout << endl;

	cout << "unsigned(x)      = " << unsigned(x) << endl;
	cout << "unsigned(x) 二进制 " << bitset<32>(unsigned(x)) << endl;
	cout << "unsigned(y)      = " << unsigned(y) << endl;
	cout << "unsigned(y) 二进制 " << bitset<32>(unsigned(y)) << endl;
	cout << endl;

	cout << "x + y              = " << x + y << endl;
	cout << "x + y 二进制         " << bitset<32>(y + x) << endl;
	cout << "signed(x + y)      = " << signed(x + y) << endl;
	cout << "signed(x + y) 二进制 " << bitset<32>(signed(x + y)) << endl;
	system("pause");
	return 0;
}

在涉及到有符号数和无符号数的比较时,c++的语法允许这样的比较,但是在编译的过程中会有warning提示。
一般来说很多人都不会刻意的去处理warning,而只是在有error的时候才认真修改bug,直到吃过n次亏之后才知道warning也是个不小的隐患。像有符号数和无符号数的比较这种问题经常会在循环遍历容器的时候使用到,
例如for(int i=0;i<arr.size();i++),其中int是有符号数,arr.size()返回的size_type是无符号数。
在某些情况下,该warning会成为一个直接影响程序功能的bug!
以上面代码为例子,-8和7比较大小的结果输出的是:
在这里插入图片描述

-8竟然大于7,这搁谁受得了啊!这要是换一个循环什么的逻辑,你能想到是因为这个出错吗?
保护头发,从我做起,读一读本文让你深刻的记住这个隐藏的bug,这波你血赚不亏!

二、问题分析

1、有符号数与无符号数的存储

数据存储在计算机中采取的都是二进制编码存储,c++采取的是二进制补码,正数的二进制码就是它的二进制补码,负数的绝对值的二进制码按位取反再加一就是它的补码。

  • 举例子
	cout << bitset<32>(1) << endl;//补码:00000000000000000000000000000001
	cout << bitset<32>(-1) << endl;//补码:11111111111111111111111111111111

那么再来看一下-8和7的数据存储,一个发现就是无论是有符号数还是无符号数他们的二进制编码是一样的,不过signed将二进制编码的首位视为符号位,unsigned则没有符号位一说,所以输出的结果就如例子中一样有了差距。总结起来就是,读取的是同一个编码却有了不同的理解和翻译。

	int x = -8;
	unsigned y = 7;
	cout << "x      = " << x << endl;
	cout << "x 二进制 " << bitset<32>(x) << endl;
	cout << "y      = " << y << endl;
	cout << "y 二进制 " << bitset<32>(y) << endl;
	cout << endl;

	cout << "unsigned(x)      = " << unsigned(x) << endl;
	cout << "unsigned(x) 二进制 " << bitset<32>(unsigned(x)) << endl;
	cout << "unsigned(y)      = " << unsigned(y) << endl;
	cout << "unsigned(y) 二进制 " << bitset<32>(unsigned(y)) << endl;
	cout << endl;
  • 输出结果
    在这里插入图片描述

2、有符号数与无符号数的运算

在c++的运算中,signed会被转化为unsigned。-8如果被当做unsigned参与运算的话自然而然的就会变成数字4294967295,所以运算得到的结果也就不可能正确了。

	cout << "x + y              = " << x + y << endl;
	cout << "x + y 二进制         " << bitset<32>(y + x) << endl;
	cout << "signed(x + y)      = " << signed(x + y) << endl;
	cout << "signed(x + y) 二进制 " << bitset<32>(signed(x + y)) << endl;

在这里插入图片描述
回到一开始提到的+7和-8的大小比较,结果输出的是-8也就是由于在无符号的情况下,-8变成了4294967295远大于7。
至此,原因分析over。

三、解决方案

1.都使用unsigned 类型。
2.或者评估实际运行中值的范围,仅使用安全范围内(UINT_MIN~INT_MAX)的值。
在这里插入图片描述

❤️❤️❤️ 给你一个有爱的眼神,看过本文千万不要忘了点赞、关注、收藏哦!灰常感谢! ❤️❤️❤️

评论 23
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值