没事造轮子没事造轮子

没事造轮子

负数大于正数?

  • W_Z_C
  • 阅读约 1 分钟
负数大于正数?

今天在代码中发现一个奇怪的现象,抽取问题模拟代码如下:

int main()
{
	int x = -1;
	unsigned int y = 1;

	assert(x < y);

	return 0;
}

运行断言竟然没有通过,整个人处于懵逼状态。缓了缓神,发现变量 x, y 类型不同,显然这是一个隐式转换的 bug。既然发现了,解决起来就很简单了,但如果不注意这种问题就很容易忽略。

为了追查到底,我翻看了标准文档:

C++标准文档

C++ 标准文档显然没有准备照顾外国友人,只有英文版,不过还是能大致的看出来,signed interger 和 unsigned interger 遇见的时候,运行结果竟然有很多分支选项,google 了一下,感觉这篇文章的例子比较容易理解: C++ Implicit Conversion (Signed + Unsigned)

#include 

signed int s1 = -4;
unsigned int u1 = 2;

signed long int s2 = -4;
unsigned int u2 = 2;

signed long long int s3 = -4;
unsigned long int u3 = 2;

int main()
{
std::cout << (s1 + u1) << "\n"; // 4294967294
std::cout << (s2 + u2) << "\n"; // -2 
std::cout << (s3 + u3) << "\n"; // 18446744073709551614  
}

First clause: types of equal rank, so the signed int operand is converted to unsigned int. This entails a value-transformation which (using two's complement) gives te printed value.

Second clause: signed type has higher rank, and (on this platform!) can represent all values of the unsigned type, so unsigned operand is converted to signed type, and you get -2

Third clause: signed type again has higher rank, but (on this platform!) cannot represent all values of the unsigned type, so both operands are converted to unsigned long long, and after the value-transformation on the signed operand, you get the printed value.

结论:都用 int 早就没这么多鸟事了……