将char转换为short时如何避免使用0xFF前缀?

问题描述 投票:0回答:2

当我做:

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,但它似乎不太清楚。

c++ hex storage
2个回答
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;
}

0
投票

一个更直接的方法是将signed char投射到unsigned char。换句话说,这个:

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

产生预期的结果:

3a
8c

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

© www.soinside.com 2019 - 2024. All rights reserved.