[英]C++ - Bit-wise not of uchar produces int
我对按位不应用于未签名字符的C ++的行为感到惊讶。
取二进制值01010101b
,即0x55
或85
。 对八位表示形式不按位应用应产生10101010b
,即0xAA
或170
。
但是,我无法在C ++中重现以上内容。 以下简单断言失败。
assert(static_cast<unsigned char>(0xAAu) == ~static_cast<unsigned char>(0x55u));
我印刷的值0x55
, 0xAA
,和~0x55
用下面的代码(如UCHAR)。 它揭示了按位操作不符合我的预期。
std::cout << "--> 0x55: " << 0x55u << ", 0xAA: " << 0xAAu << ", ~0x55: "
<< static_cast<unsigned>(~static_cast<unsigned char>(0x55u)) << std::endl;
--> 0x55: 85, 0xAA: 170, ~0x55: 4294967210
为~0x55
打印的数字等于11111111111111111111111110101010b
,这是32位按位而不是0x55
。 因此,即使我将输入显式转换为unsigned char
, ~
运算符仍在对32位整数进行运算。 这是为什么?
我应用了另一个测试,以查看~
运算符返回的类型。 结果是在一个unsigned char
输入上为int
:
template <class T>
struct Print;
// inside main()
Print<decltype(~static_cast<unsigned char>(0x55))> dummy;
产生以下编译器错误,该错误指示结果为int
类型。
error: implicit instantiation of undefined template 'Print<int>'
Print<decltype(~static_cast<unsigned char>(0x55u))> dummy;
我究竟做错了什么? 或者,如何使C ++从~0x55
产生0xAA
?
完整代码在这里
整体提升是在~
的操作数上执行的,我们可以通过转到C ++标准草案第5.3.1
节一元运算符来看到这一点,其中( 强调我的 ):
〜的操作数应具有整数或无范围的枚举类型; 结果是一个操作数的补码。 进行整体促销。 结果的类型是提升的操作数的类型[...]
和积分促销活动在部分涵盖4.5
整体促销活动 ,并说:
如果int可以表示源类型的所有值,则整数转换等级(4.13)小于int等级的bool,char16_t,char32_t或wchar_t以外的整数类型的prvalue可以转换为int类型的prvalue ;
为了完整起见,要查看未签名的char等级小于int的等级,我们可以转到第4.13
节“ Integer conversion rank” ,它说:
有符号整数类型的等级应大于任何较小尺寸的有符号整数类型的等级。
和:
字符的等级应等于有符号字符和无符号字符的等级。
一种解决方案是将结果分配给无符号字符 ,这是安全的,因为您不必担心有符号整数溢出。
正如Ben Voigt指出的那样,它将具有一个sizeof (int) == 1
且CHAR_BIT >= 32
。 在这种情况下,未签名char woudl的等级不小于int,因此晋升为unsigned int。 我们不知道这种情况实际发生的任何系统。
关于整体晋升的答案是正确的。
您可以通过按正确的顺序进行铸造和注释来获得所需的结果:
assert(static_cast<unsigned char>(0xAAu) == static_cast<unsigned char>(~0x55u));
通过分配的结果,你可以种“截断”的龙头1周的~0x55
一个unsigned char
:
#include <iostream>
int main()
{
unsigned char input = 0x55;
unsigned char output = ~input;
std::cout << "input: " << (int)input << " output: " << (int)output << std::endl;
return 0;
}
结果:
input: 85 output: 170
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.