我试图找到一些能够接受两个无符号字符并抓住一个4位低位并将其连接到其他8位前面的东西。
x = 01234567
y = 23458901
doBitWise = 890101234567
是我正在寻找的一个例子。
unsigned char x = someNumber;
unsigned char y = someNumber;
uint16_t result = (x & (1 << 4) - 1) | (y);
但是这给了我一个警告,说结果会比uint16_t更大?我错过了什么吗?
答案 0 :(得分:4)
警告是因为表达式uint16_t result = (x & (1 << 4) - 1) | (y);
中发生了算术转换。这里(1<<4)-1
的类型为int,x的类型为unsigned char
,根据转换规则,结果的类型为int
,不适合{{1}在你的平台上。
参考,c11 std 6.3.1.8关于常规算术转换:
否则,如果带有符号整数类型的操作数的类型可以表示 那么,带有无符号整数类型的操作数类型的所有值 具有无符号整数类型的操作数将转换为该类型 带有符号整数类型的操作数。
要获取uint16_t
的低4位,请使用x
。在应用移位操作之前,还将其强制转换为x & 0xF
uint16_t
这会将x的低4位置于y之前。你使用的表达式将x或x的4位降低或降低,它不能达到你想要的效果。
答案 1 :(得分:2)
这就是我想要做的事情,只需取y的最后4位并将其全部放入x。得到12位结果
x = 01234567
y = 23458901
doBitWise = 890101234567
在这种情况下,您应该将 y 移动8,并屏蔽前4位:
uint16_t result = (((unsigned short)y << 8) & 0xF00) | x; //result will be casted to uint16_t
注意:注意运算符优先级。 +来自&lt;&lt;,因此需要括号
注2:当int为16位时,要防止未定义的行为,并确保y&lt;&lt;的结果8将至少具有16位,添加显式转换为无符号short(因为y最初是unsigned char)。此外,x的插入使用按位OR运算符|。
答案 2 :(得分:1)
正如其他人所说,这里的问题是在进行算术运算之前,窄整数类型会转换为int
,这是一种有符号的类型。但是解决方案应该更简单,只需强制无符号算术:
uint16_t result = (x & (1U << 4) - 1U) | (y);
此处,文字为unsigned
,因此是<<
,&
,-
和|
运算符的结果。这是因为如果这些运算符与int
和unsigned
一起呈现,则会将int
部分转换为unsigned
。
对于从unsigned
到uint16_t
的最终转换,这总是由模运算很好地定义,并且没有理智的编译器应该抱怨这一点。