将两个无符号字符连接成一个 uint16_t
Concatenate two unsigned chars to be one uint16_t
我正在尝试纠正一些需要两个无符号字符并获取一个字符的低 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?我错过了什么吗?
警告是因为表达式 uint16_t result = (x & (1 << 4) - 1) | (y);
中发生了算术转换。这里(1<<4)-1
是int类型,x是unsigned char
类型,根据转换规则,结果是int
类型,不适合[=15] =] 在您的平台上。
参考,c11 std 6.3.1.8 关于常用算术转换:
Otherwise, if the type of the operand with signed integer type can represent
all of the values of the type of the operand with unsigned integer type, then
the operand with unsigned integer type is converted to the type of the
operand with signed integer type.
要获取 x
的低 4 位,请使用 x & 0xF
。在应用移位操作之前也将其转换为 uint16_t
,
uint16_t result = (uint16_t)(((x & 0xF) << 8) | y);
这会将 x 的低 4 位放在 y 的前面。您使用的表达式将 x 或 y 降低 4 位,它不符合您的要求。
Thats what Im wanting to do, just take the last 4 bits of y and put it with all of x. Making a 12 bit result
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
注意:注意运算符的优先级。 + 出现在 << 之前,因此需要括号
注意 2:为防止 int 为 16 位时发生未定义的行为并确保 y << 8 的结果至少为 16 位,添加了对 unsigned short 的显式转换(因为 y 最初是无符号字符)。此外,x 的插入是使用按位或运算符 |.
正如其他人所说,这里的问题是在进行算术运算之前,窄整数类型被转换为 int
,一种带符号的类型。但解决方案应该更简单,只需强制无符号算术:
uint16_t result = (x & (1U << 4) - 1U) | (y);
在这里,文字是 unsigned
,<<
、&
、-
和 |
运算符的结果也是如此。这是因为这些运算符,如果与 int
和 unsigned
一起出现,总是将 int
部分转换为 unsigned
.
对于从 unsigned
到 uint16_t
的最终转换,这始终由模运算很好地定义,没有理智的编译器应该抱怨这个。
我正在尝试纠正一些需要两个无符号字符并获取一个字符的低 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?我错过了什么吗?
警告是因为表达式 uint16_t result = (x & (1 << 4) - 1) | (y);
中发生了算术转换。这里(1<<4)-1
是int类型,x是unsigned char
类型,根据转换规则,结果是int
类型,不适合[=15] =] 在您的平台上。
参考,c11 std 6.3.1.8 关于常用算术转换:
Otherwise, if the type of the operand with signed integer type can represent all of the values of the type of the operand with unsigned integer type, then the operand with unsigned integer type is converted to the type of the operand with signed integer type.
要获取 x
的低 4 位,请使用 x & 0xF
。在应用移位操作之前也将其转换为 uint16_t
,
uint16_t result = (uint16_t)(((x & 0xF) << 8) | y);
这会将 x 的低 4 位放在 y 的前面。您使用的表达式将 x 或 y 降低 4 位,它不符合您的要求。
Thats what Im wanting to do, just take the last 4 bits of y and put it with all of x. Making a 12 bit result
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
注意:注意运算符的优先级。 + 出现在 << 之前,因此需要括号
注意 2:为防止 int 为 16 位时发生未定义的行为并确保 y << 8 的结果至少为 16 位,添加了对 unsigned short 的显式转换(因为 y 最初是无符号字符)。此外,x 的插入是使用按位或运算符 |.
正如其他人所说,这里的问题是在进行算术运算之前,窄整数类型被转换为 int
,一种带符号的类型。但解决方案应该更简单,只需强制无符号算术:
uint16_t result = (x & (1U << 4) - 1U) | (y);
在这里,文字是 unsigned
,<<
、&
、-
和 |
运算符的结果也是如此。这是因为这些运算符,如果与 int
和 unsigned
一起出现,总是将 int
部分转换为 unsigned
.
对于从 unsigned
到 uint16_t
的最终转换,这始终由模运算很好地定义,没有理智的编译器应该抱怨这个。