右移无符号字符是否填充了字符?

问题描述

在我的系统上,(unsigned char) -1 是(预期用于 8 位字符)二进制 1111 1111(十进制 255)。

同样,(unsigned char) -1 >> 1 是预期的 0111 1111。左边填充了一个零。

~((unsigned char) -1 >> 1) 是预期的 1000 0000。

现在我想生成无符号字符 0010 0000 例如。

我试过 ~((unsigned char) -1 >> 1) >> 2,但输出 1110 0000 .... 什么?怎么左边突然就被填满了?


如何生成启用第 n 位(从左起)的 unsigned char

我愿意

n   unsigned char
0   1000 0000
1   0100 0000
2   0010 0000
3   0001 0000
... 
7   0000 0001

目前,~((unsigned char) -1 >> 1) >> n 正在给我

n   unsigned char
0   1000 0000
1   1100 0000
2   1110 0000
3   1111 0000
... 
7   1111 1111

此问题存在于 uint8_tuint16_t,但在 uint32_t 及更高版本不再发生。

解决方法

由于整数提升,当几乎对值执行任何操作时,unsigned char 会提升为 int

当您右移时,左操作数进行整数提升,unsigned char 将变为 int。表达式的值将是提升后左操作数的值 - 因此 ((unsigned char) -1 >> 1) 的结果值为 127,类型为 int。如果你 ~ (int)127 你会得到一个带有符号位设置的 int;转移该权利将具有实现定义的行为。

解决方案是在外部 ~ 周围添加一个演员

(unsigned char)~((unsigned char) -1 >> 1) >> 2

或者,& 带有 0xFF 的值:

(~((unsigned char) -1 >> 1) >> 2) & 0xFF

至于设置n左边的第unsigned char位,最好的办法是*左移1UAllan Wind所示的位置。

,

另一种设置第 n 位的方法(从左边开始):

1 << (CHAR_BIT - n - 1)
,

您可以利用 std::numeric_limits<T>::digits 创建一个不太混淆且灵活的代码:

    unsigned char data=0;
    
    const uint8_t sizeBit=std::numeric_limits<decltype(data)>::digits;
    for(uint8_t n=0;n<sizeBit;n++) {
        data = 1 << (sizeBit - (n+1));
        std::bitset<sizeBit> x(data);
        std::cout << x << '\n';
    }

打印:

10000000
01000000
00100000
00010000
00001000
00000100
00000010
00000001