C++ - 不是uchar的比特产生int

Lem*_*ing 7 c++ bit-manipulation integer-promotion

当将bit-wise应用于unsigned char时,我对C++的行为感到惊讶.

取二进制值01010101b,即0x5585.在8位表示上不按比特应用应该产生10101010b,即0xAA,或170.

但是,我无法在C++中重现上述内容.以下简单断言失败.

assert(static_cast<unsigned char>(0xAAu) == ~static_cast<unsigned char>(0x55u));
Run Code Online (Sandbox Code Playgroud)

我印刷的值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
Run Code Online (Sandbox Code Playgroud)

打印的数字~0x55等于11111111111111111111111110101010b,而不是32位的位数0x55.因此,~即使我明确地将输入转换为a ,操作符也在32位整数上运行unsigned char.这是为什么?

我应用了另一个测试来查看~运算符返回的类型.结果intunsigned char输入:

template <class T>
struct Print;

// inside main()    
Print<decltype(~static_cast<unsigned char>(0x55))> dummy;
Run Code Online (Sandbox Code Playgroud)

产生以下编译器错误,表明结果是类型int.

error: implicit instantiation of undefined template 'Print<int>'
    Print<decltype(~static_cast<unsigned char>(0x55u))> dummy;
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?或者说,我怎么C++产生0xAA~0x55

完整代码在这里

Sha*_*our 9

~我们可以通过转到草案C++标准部分的5.3.1 一元运算符(强调我的)来看到操作数上的整体促销:

〜的操作数应具有整数或无范围的枚举类型; 结果是其操作数的一个补码.执行整体促销.结果的类型是提升的操作数的类型[...]

积分促销活动将在4.5 整体促销部分中介绍,并说:

如果int可以表示源类型的所有值,则除了bool,char16_t,char32_t或wchar_t之外的整数类型的prvalue(其整数转换等级(4.13)小于int的等级)可以转换为int类型的prvalue ;

为了完整性,要看到unsigned char rank小于int的等级,我们可以转到4.13 Integer转换等级,其中说:

有符号整数类型的等级应大于具有较小大小的任何有符号整数类型的等级.

和:

char的等级应等于signed char和unsigned char的等级.

一种解决方案是将结果分配给unsigned char,这是安全的,因为您不必担心有符号整数溢出.

作为本福格特指出,将符合有一个系统,sizeof (int) == 1CHAR_BIT >= 32.在这种情况下,unsigned char的等级woudl不小于int,因此促销将是unsigned int.我们不知道实际发生的任何系统.