比较有符号和无符号字符

Comparison signed and unsigned char

本文关键字:无符号 字符 符号 比较      更新时间:2023-10-16

这似乎很奇怪。我发现了误解。我使用带有字符的 gcc 作为签名字符。我一直认为在比较表达式(和其他表达式)中,如有必要,有符号值会转换为无符号值。

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,并且 如果它是假的,则为假。

所以在这个表达中

b == a

的示例

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

这两个操作数都转换为类型 int 。作为结果,有符号字符传播其有符号位,两个值变得不相等。

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

{
    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 negativen";
}

输出为

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 ahould 不存在。

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

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

按照算术转换规则,比较的评估公式为:

((unsigned int) b == (unsigned int) a)(0xfffc == 0xfffc),这是(1)


在第两种情况下: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因为无符号值可以转换为有符号值,而不是viceversa(如您所说)。