当我做:
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,但它似乎不太清楚。
如果以十进制而不是十六进制查看它,您的输出可能更有意义:
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;
}
一个更直接的方法是将signed char
投射到unsigned char
。换句话说,这个:
cout << std::hex << (short)(unsigned char)('\x3A') << std::endl;
cout << std::hex << (short)(unsigned char)('\x8C') << std::endl;
产生预期的结果:
3a
8c
但不确定这是否特别清楚。