C – 不是uchar的比特产生int

前端之家收集整理的这篇文章主要介绍了C – 不是uchar的比特产生int前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
当我将bit-wise应用于unsigned char时,我对C的行为感到惊讶.

取二进制值01010101b,即0x55或85.按位不应用8位表示应产生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?

完整代码here

解决方法

整体促销是在操作数上执行的〜我们可以通过转到 draft C++ standard部分看到这一点5.3.1一元运算符说(强调我的):

The operand of ˜ shall have integral or unscoped enumeration type; the
result is the one’s complement of its operand. Integral promotions
are performed.
The type of the result is the type of the promoted operand […]

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

A prvalue of an integer type other than bool,char16_t,char32_t,or
wchar_t whose integer conversion rank (4.13) is less than the rank of
int can be converted to a prvalue of type int if int can represent all
the values of the source type;

为了完整性,要看到unsigned char rank小于int的等级,我们可以转到4.13整数转换等级,它表示:

The rank of a signed integer type shall be greater than the rank of
any signed integer type with a smaller size.

和:

The rank of char shall equal the rank of signed char and unsigned
char.

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

正如Ben Voigt所指出的,它将符合一个系统,其中sizeof(int)== 1和CHAR_BIT> = 32.在这种情况下,unsigned char的等级不应小于int,因此促销将是unsigned int .我们不知道实际发生的任何系统.

猜你在找的C&C++相关文章