比较signed和unsigned char

看起来很奇怪。 我发现了误解。 我使用带有char的gcc作为signed char。 我一直认为,在比较表达式(和其他表达式)中,如果需要,有符号值将转换为unsigned。

int a = -4; unsigned int b = a; std::cout << (b == a) << std::endl; // writes 1, Ok 

但问题是

 char a = -4; unsigned char b = a; std::cout << (b == a) << std::endl; // writes 0 

比较运算符的神奇之处在于它不仅仅是按位吗?

根据C ++标准

6如果两个操作数都是算术或枚举类型,则对两个操作数执行通常的算术转换; 如果指定的关系为真,则每个运算符应为true,如果为false则为false。

所以在这个表达中

 b == a 

这个例子

 char a = -4; unsigned char b = -a; std::cout << (b == a) << std::endl; // writes 0 

两个操作数都转换为int类型。 结果签名char propagets其签名位和两个值变得不相等。

要演示效果,请尝试运行此简单示例

 { char a = -4; unsigned char b = -a; std::cout << std::hex << "a = " << ( int )a << "'\tb = " << ( int )b << std::endl; if ( b > a ) std::cout << "b is greater than a, that is b is positive and a is negative\n"; } 

输出是

 a = fffffffc' 'b = 4 b is greater than a, that is b is positive and a is negative 

编辑:只是现在我已经看到变量的定义必须看起来像

  char a = -4; unsigned char b = a; 

这是b定义中的减号,不应该存在。

由于(unsigned) int至少为16位宽,因此我们将其用于指导目的:

在第一种情况下: a = 0xfffcb = (unsigned int) (a) = 0xfffc

遵循算术转换规则 ,比较评估为:

((unsigned int) b == (unsigned int) a)(0xfffc == 0xfffc) ,即(1)


a = 0xfc情况下: a = 0xfcb = (unsigned char) ((int) a)或:

b = (unsigned char) (0xfffc) = 0xfc符号扩展为(int)和截断

因为和int可以表示signed charunsigned char类型的范围,所以比较被评估为:( 零扩展与符号扩展)

((int) b == (int) a)(0x00fc == 0xfffc) ,即(0)


注意:在这些情况下, C和C ++整数转换规则的行为方式相同。 当然,我假设char类型是8位,这是典型的,但只是最低要求。

它们都输出0因为无符号值可以转换为有符号值,而不是反之亦然(就像你说的那样)。