将两个无符号字符连接成一个uint16_t

时间:2016-04-24 02:38:17

标签: c bit-manipulation bitwise-operators

我试图找到一些能够接受两个无符号字符并抓住一个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更大?我错过了什么吗?

3 个答案:

答案 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,因此是<<&-|运算符的结果。这是因为如果这些运算符与intunsigned一起呈现,则会将int部分转换为unsigned

对于从unsigneduint16_t的最终转换,这总是由模运算很好地定义,并且没有理智的编译器应该抱怨这一点。