【问题标题】:How to avoid 0xFF prefix when converting char to short?将char转换为short时如何避免0xFF前缀?
【发布时间】:2019-03-12 20:54:55
【问题描述】:

当我这样做时:

cout << std::hex << (short)('\x3A') << std::endl;
cout << std::hex << (short)('\x8C') << std::endl;

我希望得到以下输出:

3a
8c

但是,我有:

3a
ff8c

我想这是由于char——更准确地说是一个签名char——存储在内存中的方式:0x80 以下的所有内容都不会加上前缀;另一方面,0x80 及以上的值将以 0xFF 为前缀。

当给定signed char 时,如何获得其中实际字符的十六进制表示?换句话说,我如何获得\x3A 的0x3A 和\x8C 的0x8C?

我认为条件逻辑在这里不太适合。虽然我可以在需要时从生成的 short 中减去 0xFF00,但这似乎不是很清楚。

【问题讨论】:

  • 你为什么首先使用 char ?为什么不是 0x3a 等? ff 来自符号扩展,因为您的编译器碰巧考虑了 char 签名。结果是(有符号)短,但十六进制输出模式将所有整数视为无符号,因此您看到 ff 但没有负号。
  • @CruzJean:上下文是char 来自包含二进制数据的char *。前两个字节对应一个标识符。为了重构标识符,我使用了unsigned short id = (unsigned short)d[0] * 256 + d[1],在某些情况下,这并没有给出我最初期望的结果。
  • 数据写成短裤了吗?
  • @CruzJean:因为 ID 是两个字节长,我会说是的,unsigned short
  • 如果它被写成短片,你应该把它读成短片。手动组合两个字节假定具有特定的字节顺序,并且比直接读取为短字节要慢。

标签: c++ hex storage


【解决方案1】:

如果您以十进制而不是十六进制查看,您的输出可能更有意义:

std::cout << std::dec << (short)('\x3A') << std::endl;
std::cout << std::dec << (short)('\x8C') << std::endl;

输出:

58
-116

这些值被转换为short,因此我们(最常见)处理的是 16 位值。 -116 的 16 位二进制表示为 1111 1111 1000 1100,在十六进制中变为 FF8C。因此,根据您的要求,输出是正确的(在 char 是有符号类型的系统上)。 与其说是char 存储在内存中的方式,不如说是解释位的方式。作为无符号值,8 位模式1000 1100 表示-116,转换为short 应该是保留这个值,而不是保留位。

十六进制 8C 的所需输出对应于(对于 short)十进制值 140。要从 8 位中获取此值,必须将该值解释为无符号 8 位值(因为最大的有符号 8 位值是 127)。所以数据需要被解释为unsigned char,然后才能扩展为short。对于示例代码中的字符文字,如下所示。

std::cout << std::hex << (unsigned short)(unsigned char)('\x3A') << std::endl;
std::cout << std::hex << (unsigned short)(unsigned char)('\x8C') << std::endl;

最有可能的是,真正的代码会有变量而不是字符文字。如果是这种情况,那么与其强制转换为unsigned char,不如将​​变量声明为unsigned char 类型可能更方便。 这可能是您无论如何都应该使用的类型,基于您希望查看其十六进制值这一事实。不是明确的,但这确实表明该值被简单地视为一个数据字节而不是一个数字,这表明无符号类型是合适的。你看过std::byte吗?

另一个漂亮的想法要扔掉:以下还给出了所需的输出,作为使用 unsigned char 变量的合理复制。

#include <iostream>

unsigned char operator "" _u (char c) { return c; } // Suffix for unsigned char literals

int main()
{
    std::cout << std::hex << (unsigned short)('\x3A'_u) << std::endl;
    std::cout << std::hex << (unsigned short)('\x8C'_u) << std::endl;
}

【讨论】:

    【解决方案2】:

    更直接的方法是将signed char 转换为unsigned char。换句话说,这是:

    cout << std::hex << (short)(unsigned char)('\x3A') << std::endl;
    cout << std::hex << (short)(unsigned char)('\x8C') << std::endl;
    

    产生预期的结果:

    3a
    8c
    

    但不确定这一点是否特别清楚。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-20
      • 2017-08-17
      • 1970-01-01
      • 2013-12-12
      • 1970-01-01
      相关资源
      最近更新 更多