【问题标题】:Convert hex string into unsigned char in C++在 C++ 中将十六进制字符串转换为无符号字符
【发布时间】:2015-09-12 04:52:51
【问题描述】:

我想将字符串中的十六进制表示转换为 unsigned char 变量,如下所示:

std::stringstream ss;
uint8_t x;
ss << "1f";
ss >> std::hex >> x;  // result: x = 0x31 (=49 in decimal and ='1' as char)

显然,我假设转换将导致 x = 0x1f(十进制 = 31),因为 0x1f 小于 0xff,这是可以存储在 8 位无符号字符中的最大值。 相反,在转换中只使用了我的字符串的前 8 位。

有人可以向我解释为什么会发生这种情况以及如何解决它吗?

【问题讨论】:

  • 你确定解析十六进制数字不需要前缀 0x 吗? (例如,用“0x1f”输入流)

标签: c++ string hex stringstream


【解决方案1】:

std::uint8_t 是(通常见下文)unsigned char 的别名,corresponding operator&gt;&gt; 将其视为字符类型而不是整数类型。正因为如此,字符'1'被读入x,它的ASCII值是49。'1'的ASCII值的十六进制恰好是你要解析的值的十进制是巧合;尝试解析 "1e""10""1xyz" 仍会导致 x == 49

要解决这个问题,先解析成另一种整数类型,然后缩小到 8 位:

std::stringstream ss;
uint8_t x;
unsigned tmp;

ss << "1f";
ss >> std::hex >> tmp; 
x = tmp;                // may need static_cast<uint8_t>(tmp) to suppress
                        // compiler warnings.

迂腐附录(主要是历史意义)

如果我们是完全迂腐的,uint8_t 是一个可选的 (!) 实现定义的无符号整数类型,如果存在,它正好是 8 位宽。 C++ 将定义推迟到 [cstdint.syn]/2 中的 C 标准,而 C99 在 7.18.1.1 中定义:

1 typedef 名称intN_t 指定宽度为N、无填充位和二进制补码表示的有符号整数类型。因此,int8_t 表示宽度正好为 8 位的有符号整数类型。

2 typedef 名称uintN_t 指定宽度为N 的无符号整数类型。因此,uint24_t 表示宽度正好为 24 位的无符号整数类型。

3 这些类型是可选的。但是,如果实现提供了宽度为 8、16、32 或 64 位的整数类型,则应定义相应的 typedef 名称。

背景是历史。曾几何时,存在一个字节没有 8 位的平台,例如许多 PDP(更不用说像早期的 UNIVAC1 这样的十进制计算机)。今天我们很少对这些感兴趣,但它们在设计 C 时很重要,因此,如果今天开发 C,可能会做出某些假设,而 C 标准中没有做出这些假设。

在这些平台上,8 位整数类型并不总是很容易提供,并且unsigned char 被定义为恰好一个字节宽,如果一个字节不是 8 位宽,则不能同时恰好是 8 位宽.这一点,连同其他一些东西2,就是为什么所有uintN_t 类型都是可选的,也是为什么它们都没有与特定的整数类型绑定的原因。目的是定义提供特定低级行为的类型。如果实现不能提供这种行为,至少它会出错而不是编译废话。

因此,完全迂腐:如果您完全使用uint8_t,则可以编写一个完全拒绝您的代码的符合C++ 实现。也可以编写一个符合要求的实现,其中uint8_t 是一个不同于unsigned char 的整数类型,其中问题中的代码可以正常工作。

然而,在实践中,您不太可能遇到这样的实现。我知道的所有当前 C++ 实现都将 uint8_t 定义为 unsigned char 的别名。3

1 即使这不是兔子洞的深度,尽管我怀疑 C 的创建者是否考虑过 Setun(俄罗斯平衡三进制计算机)。

2 例如,并非所有这些机器都将整数表示为二进制补码。

3如果您知道哪一个不知道,请发表评论,我会在此处记录下来。我想可能有一个微控制器工具包有理由偏离。

【讨论】:

  • 只是好奇,为什么std::uint8_t 没有成为一个新的整数类型?
  • @anxieux 引入uint8_t 和其他固定宽度类型的第一个C 实现是在现有整数类型的基础上实现的; uint8_tunsigned char 那里,而且从未改变。严格来说,可以编写一个执行您建议的实现(请参阅我编辑的迂腐附录),但我认为它从未完成过。
猜你喜欢
  • 2017-01-11
  • 2013-03-22
  • 2018-01-31
  • 2015-01-11
  • 1970-01-01
  • 2022-07-22
  • 2015-02-18
  • 2017-05-30
  • 2021-04-28
相关资源
最近更新 更多