问题描述
在我的系统上,(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_t
、uint16_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
位,最好的办法是*左移1U
到Allan 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