【问题标题】:Comparison signed and unsigned char比较有符号和无符号字符
【发布时间】:2014-01-28 10:07:43
【问题描述】:

看起来很奇怪。我发现了误会。我将 gcc 与 char 一起用作签名字符。我一直认为在比较表达式(和其他表达式)中,如有必要,有符号值会转换为无符号值。

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

如果不只是按位,比较运算符有什么魔力?

【问题讨论】:

  • 第一个输出1,你确定吗? Gcc disagrees.
  • 第一个和第二个都不输出1
  • 是的,第一个输出1,第二个输出0。都是默认促销的结果。
  • @R..,再次,no, they don't.
  • 这两种情况你不是说unsigned xxx b = a; 吗?它可以解释混乱。

标签: c++ c unsigned-char


【解决方案1】:

根据 C++ 标准

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

所以在这个表达式中

b == a

例子

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

两个操作数都转换为int 类型。结果,signed char 传播了它的有符号位,两个值变得不相等。

为了演示效果尝试运行这个简单的例子

{
    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 定义中的负号不应该出现。

【讨论】:

  • 不,不(好吧,至少在第一个示例中不是)。
  • 报价不完整。如果您比较相同等级的无符号和有符号类型并且“小于”int,则有符号操作数将转换为无符号类型。
  • @Jefffrey:阅读[C++11: 5/9]
  • charsigned charunsigned char 几乎总是通过“通常的算术转换”提升为(有符号)int。但如果CHAR_MAX &gt; INT_MAXUCHAR_MAX &gt; INT_MAX,则charunsigned char 将分别提升为unsigned int。仅当CHAR_BIT &gt;= 16sizeof (int) == 1 时才会发生这种情况——对于普通的char,如果char 恰好是无符号类型。在 8 位字节的系统上你永远不会遇到这种情况。
  • @VladfromMoscow:我确定它在 C 中是允许的;我几乎可以肯定它在 C++ 中是允许的。考虑CHAR_BIT == 16,普通char 是无符号的,CHAR_MAX == 65536sizeof (int) == 1INT_MAX == 32767。我有兴趣在标准中看到这将违反的条款。 (类似地,UINT_MAX &gt; LONG_MAX 甚至不是特别不寻常;char 不寻常之处在于它可以签名或未签名。)顺便说一句,如果你想在评论中通知我,你不能在at-sign 和我的名字。
【解决方案2】:

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

【讨论】:

  • 不,这两个操作数都转换为int类型即为signed int类型。
  • @VladfromMoscow,所以你是说他们都被转换成int?
  • @VladfromMoscow,我在这里说什么? “无符号值可以转换为有符号值”
  • 您的短语可能会使读者感到困惑。不清楚也不显示机制。
  • @Vlad:用“我提供了示范代码”说你;你能解释一下吗?
【解决方案3】:

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

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

arithmetic conversion rules之后,比较评估为:

((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)


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

【讨论】:

  • 原帖有错字。所以在你的第一个例子中 a 和 b 应该有相同的内部表示 0xfffc
猜你喜欢
  • 1970-01-01
  • 2021-10-31
  • 2011-07-21
  • 1970-01-01
  • 2016-08-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多