c 中的位操作和屏蔽
Bit manipulation and masking in c
我正在处理一些 C 问题。我有一个进程需要执行并且有位操作。我有 2 个 uint8 类型的变量,比如 uint8 bit_Part1
& uint8 bit_Part2
(每个 U8)。我想给这些变量添加值,一个是 U4
另一个是 U6
像 U4_part1
和 U6_part2
和一个布尔值 Bool_Part3
我想放置它们进入这些 uint8 bit_Part1
& uint8 bit_Part2
结构如下
到目前为止,我试过像这样移动:
其伪代码:
uint8 bitman_u8_part1 =0;
uint8 bitman_u8_part2 =0;
bitman_u8_part1 |= ((uint8)(U4_Part1)); // 0000\\
bitman_u8_part1 | = ((uint8)((U6_Part2 >> 2)<<4));// append 0000 for the empty
bitman_u8_part2 | =((uint8)(EC2_TCH_BITMAP_U6_Part2<<4));
bitman_u8_part2 | =((bool)BOOL_Part3 & 1<<4);
这是我希望看到的示例:
如果U4_part1=0111,U6_Part2=001111,Bool_Part3=1(真)
那么预期的结果是:
bit_Part1 & uint8 bit_Part2 都将包含数据 -> 00000|1|00||1111|0111
(注意我添加了 | 只是为了数据之间的分离 || 是为了分离 uint8 bit_Part1 和 uint8 bit_Part2)。
uint8中的附加值bit_Part2用0填充,对比上图(&U4表示4位的值,U6表示6位的值)
我该怎么做?
UPDATE:
我又试过的东西:
unsigned int U4_data1 = 12; /* 60 = 0000 1100 */
unsigned int U6_data2 = 53; /* 21 = 0011 0101 */
unsigned int Bool_data3 =1;
unsigned int U8_part1 =0;
unsigned int U8_part2 = 0;
U8_part1 = U4_data1;
U8_part1 |= (U6_data2<<4);
printbinary(U8_part1);
U8_part2 |= U6_data2>>4;
U8_part2 |= (Bool_data3)<<2;
// Assemble the pieces in a temporary object:
uint16_t temp = Bool_Part3 << 10
| U6_part2 << 4
| U4_part1 << 0;
// Redivide the temporary object into the destination parts:
uint8_t bit_Part1 = temp >> 0;
uint8_t bit_Part2 = temp >> 8;
如果 Bool_Part3
有一些您调用布尔值的整数类型,即使它不是标准的 _Bool
或 bool
(在 <stdbool.h>
中声明)类型,并且可能具有 0 或 1 以外的值,则确保在结果中插入 0 或 1 的适当方法是将其转换为 _Bool
,如:
uint16_t temp = (_Bool) Bool_Part3 << 10 …
虽然您可以使用其他习语,例如 !!Bool_Part3
,但强制转换的优点是可以显式表达所需的操作,转换为 0 或 1。(虽然 30 年前的程序员不得不使用各种变通方法在 C 中,当现代表达式可用时,没有理由像人们几十年前那样对 kludges 进行编程。)
备注:
uint8_t
和 uint16_t
在 <stdint.h>
中声明。
- 为了说明和统一,显示了零偏移。它们可以被省略。
我会提出以下建议:
#define LOW_4_MASK 0xF
#define LOW_2_MASK 3
#define BOOL_PART3_BIT = 1 << 2;
bit_Part1 = (U4_Part1 & LOW_4_MASK) | ((U6_part2 & LOW_4_MASK) << 4);
bit_Part2 = (U6_part2 >> 4) & LOW_2_MASK;
if (Bool_Part3)
bit_Part2 |= BOOL_PART3_BIT;
我不知道这里所有变量的类型,或者是否存在设置其他位的可能性,例如 U6_part2
的六位范围之外。屏蔽可防止错误设置的杂散位传播到生成的 bit_Part1
和 bit_Part2
变量中。
我单独处理了布尔值,因为很多 C 代码中的布尔值(包括您所写的摘录)是一个整数(只有较新的 C 标准修改了它,并且很多 C 代码不使用较新的 bool 定义);任何非零值都算作“真”。例如,如果您将 Bool_Part3
设置为 0xFFF0 并进入这段代码,您当然不希望将它与结果进行“或”运算。即使你把它屏蔽到最低位,你也可能得不到正确的结果。
这是另一种使用联合的方法。只需将 1 替换为您的布尔变量,将 15 替换为 U6,将 7 替换为 U4。
#include <stdio.h>
int main()
{
struct st_bitman_u8 {
unsigned char part1;
unsigned char part2;
}bitman_u8;
union Data {
short sum;
struct st_bitman_u8 _bitman_u8;
}data;
short sum1 = 1 << 10; //1 is Bool_Part3
short sum2 = 15 << 4; //15 is U6_Part2
short sum3 = 7; //7 is U4_part1
data.sum = sum1+sum2+sum3;
printf("part1 %d part2 %d",data._bitman_u8.part1, data._bitman_u8.part2);
return 0;
}
我正在处理一些 C 问题。我有一个进程需要执行并且有位操作。我有 2 个 uint8 类型的变量,比如 uint8 bit_Part1
& uint8 bit_Part2
(每个 U8)。我想给这些变量添加值,一个是 U4
另一个是 U6
像 U4_part1
和 U6_part2
和一个布尔值 Bool_Part3
我想放置它们进入这些 uint8 bit_Part1
& uint8 bit_Part2
结构如下
到目前为止,我试过像这样移动:
其伪代码:
uint8 bitman_u8_part1 =0;
uint8 bitman_u8_part2 =0;
bitman_u8_part1 |= ((uint8)(U4_Part1)); // 0000\\
bitman_u8_part1 | = ((uint8)((U6_Part2 >> 2)<<4));// append 0000 for the empty
bitman_u8_part2 | =((uint8)(EC2_TCH_BITMAP_U6_Part2<<4));
bitman_u8_part2 | =((bool)BOOL_Part3 & 1<<4);
这是我希望看到的示例:
如果U4_part1=0111,U6_Part2=001111,Bool_Part3=1(真)
那么预期的结果是: bit_Part1 & uint8 bit_Part2 都将包含数据 -> 00000|1|00||1111|0111
(注意我添加了 | 只是为了数据之间的分离 || 是为了分离 uint8 bit_Part1 和 uint8 bit_Part2)。
uint8中的附加值bit_Part2用0填充,对比上图(&U4表示4位的值,U6表示6位的值)
我该怎么做?
UPDATE:
我又试过的东西:
unsigned int U4_data1 = 12; /* 60 = 0000 1100 */
unsigned int U6_data2 = 53; /* 21 = 0011 0101 */
unsigned int Bool_data3 =1;
unsigned int U8_part1 =0;
unsigned int U8_part2 = 0;
U8_part1 = U4_data1;
U8_part1 |= (U6_data2<<4);
printbinary(U8_part1);
U8_part2 |= U6_data2>>4;
U8_part2 |= (Bool_data3)<<2;
// Assemble the pieces in a temporary object:
uint16_t temp = Bool_Part3 << 10
| U6_part2 << 4
| U4_part1 << 0;
// Redivide the temporary object into the destination parts:
uint8_t bit_Part1 = temp >> 0;
uint8_t bit_Part2 = temp >> 8;
如果 Bool_Part3
有一些您调用布尔值的整数类型,即使它不是标准的 _Bool
或 bool
(在 <stdbool.h>
中声明)类型,并且可能具有 0 或 1 以外的值,则确保在结果中插入 0 或 1 的适当方法是将其转换为 _Bool
,如:
uint16_t temp = (_Bool) Bool_Part3 << 10 …
虽然您可以使用其他习语,例如 !!Bool_Part3
,但强制转换的优点是可以显式表达所需的操作,转换为 0 或 1。(虽然 30 年前的程序员不得不使用各种变通方法在 C 中,当现代表达式可用时,没有理由像人们几十年前那样对 kludges 进行编程。)
备注:
uint8_t
和uint16_t
在<stdint.h>
中声明。- 为了说明和统一,显示了零偏移。它们可以被省略。
我会提出以下建议:
#define LOW_4_MASK 0xF
#define LOW_2_MASK 3
#define BOOL_PART3_BIT = 1 << 2;
bit_Part1 = (U4_Part1 & LOW_4_MASK) | ((U6_part2 & LOW_4_MASK) << 4);
bit_Part2 = (U6_part2 >> 4) & LOW_2_MASK;
if (Bool_Part3)
bit_Part2 |= BOOL_PART3_BIT;
我不知道这里所有变量的类型,或者是否存在设置其他位的可能性,例如 U6_part2
的六位范围之外。屏蔽可防止错误设置的杂散位传播到生成的 bit_Part1
和 bit_Part2
变量中。
我单独处理了布尔值,因为很多 C 代码中的布尔值(包括您所写的摘录)是一个整数(只有较新的 C 标准修改了它,并且很多 C 代码不使用较新的 bool 定义);任何非零值都算作“真”。例如,如果您将 Bool_Part3
设置为 0xFFF0 并进入这段代码,您当然不希望将它与结果进行“或”运算。即使你把它屏蔽到最低位,你也可能得不到正确的结果。
这是另一种使用联合的方法。只需将 1 替换为您的布尔变量,将 15 替换为 U6,将 7 替换为 U4。
#include <stdio.h>
int main()
{
struct st_bitman_u8 {
unsigned char part1;
unsigned char part2;
}bitman_u8;
union Data {
short sum;
struct st_bitman_u8 _bitman_u8;
}data;
short sum1 = 1 << 10; //1 is Bool_Part3
short sum2 = 15 << 4; //15 is U6_Part2
short sum3 = 7; //7 is U4_part1
data.sum = sum1+sum2+sum3;
printf("part1 %d part2 %d",data._bitman_u8.part1, data._bitman_u8.part2);
return 0;
}