【问题标题】:Why is 0x82 smaller than 0x80?为什么 0x82 小于 0x80?
【发布时间】:2016-12-08 17:03:45
【问题描述】:

我正在尝试为大学课程练习优化 String 课程。 普通字符串存储为 char* 和 size_t 作为长度。 sizeof(String) 是 8,它应该保持这样。但是,如果我只有 7 个或更少字符的字符串(或者如果您考虑 null 终止符,则为 6 个),而不是使用指针,我想将它们直接存储在指针/size_t 字节中。

为此,我有两个结构,一个用于 char* 和 size_t,另一个用于 8 个字符(字节)的数组。两者我都放在一个联合中,并给 String 类一个所述联合的成员。

要确定一个字符串是普通字符串还是短字符串,我使用长度为 size_t 或 byte[7] 的最高有效位。如果 byte[7] 大于或等于 128(或 0x80),则它是一个短字符串,字符直接存储在字节中。然后将长度存储在 byte[7] 的剩余位中。

这是目前为止的理论。普通字符串位已经实现,我现在正在尝试实现短字符串位。我现在遇到的问题是以下代码:

inline const char* c_str(void) const
    {
        if (compound.bytes.bytes[7] >= 0x80)
            return compound.bytes.bytes;
        return compound.string.m_string;
    }

从 Visual Studio 观察者中,我知道 Compound.bytes.bytes[7] 是 0x82(字符串是“hi”)。所以它应该是 0x82 >= 0x80 和 true 一样并返回字节,但由于某种原因,这个比较得到 false 并返回一个普通字符串的 char*,这当然是一个虚假的指针(准确地说是 0xcc006968)。

另外值得指出的是,这段代码对于普通字符串仍然可以正常工作。

我错过了什么,我做错了什么?

【问题讨论】:

  • 因为 0x80 是负字符(请记住,字符类型是有符号的,至少在您的平台上)。
  • 你能发布一个完整的、最小的、可验证的例子吗?你描述的行为很奇怪。

标签: c++ visual-studio


【解决方案1】:

当使用有符号 8 位整数时,值 0x80 是一个负数。 因此 0x82 会更小,因为它也是负数。值 0x82 转换为 -126,0x80 转换为 -128,这意味着 0x80 小于 0x82二进制补码有符号整数强>。

将您的数据类型切换为uint8_t

【讨论】:

  • @Nikita:将十六进制值 0x80 和 0x82 转换为二进制补码表示,假设为 8 位数量,看看是否溢出。
  • 也许我真的很笨,但不是 0x80 = -128 和 0x82 = -126 吗?那么 0x80 仍然会小于 0x82 吗?极端情况下,0xFF 将是-1,并且 0x80
  • @templatetypedef:我的错,你是对的。我会编辑我的答案。谢谢。
  • 键盘 今天表现不佳。 ;-) 进行了另一次编辑。
  • 但是 OP 报告的问题是他们在某处看到 0x82,他们正在调试器中单步执行代码,并且他们看到比较 0x82 >= 0x80 发生,但比较返回错误的。您提供的解释似乎表明问题与签名有关,但即使有签名,比较仍应评估为真。你提议的改变将如何解决这个问题?
【解决方案2】:

char* 签名为 0x80 及以上为负数

【讨论】:

  • char 类型可以是 charsigned charunsigned char,具体取决于编译器设置。
  • 只有虐待狂才会使用编译器设置更改 char 的符号。
【解决方案3】:

您正在使用带符号的值 (char)。因此,0x80 表示 -128,0x82 表示 -126。此代码可能会根据您的需要工作:

inline const char* c_str(void) const
{
    if (static_cast<unsigned char>(compound.bytes.bytes[7]) >= 0x80u)
        return compound.bytes.bytes;
    return compound.string.m_string;
}

【讨论】:

    【解决方案4】:

    您将有符号字符 (0x82 = -126) 与有符号整数 (0x00000080 = 128) 进行比较。有符号字符可以是 -128 到 127 之间的数字,因此它始终小于 128。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-04-02
      • 2011-04-24
      • 1970-01-01
      • 1970-01-01
      • 2014-04-03
      • 2018-04-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多