&
& |
1 | 0 |
---|---|---|
1 | 1 | 0 |
0 | 0 | 0 |
有0为0,全1为1
|
| |
1 | 0 |
---|---|---|
1 | 1 | 1 |
0 | 1 | 0 |
有1为1,全0为0
^
^ |
1 | 0 |
---|---|---|
1 | 0 | 1 |
0 | 1 | 0 |
相同为0,相异为1
~
位取反是将操作数的二进制为逐个按位取反,注意与逻辑取反区分
<<
与右位移>>
C语言的位移运算要取决于其数据类型
- 左移时右侧补零,为逻辑位移
- 右移时左侧补零,为逻辑位移
- 左移时右侧补零,为算术位移(相当于逻辑位移)
- 右移时左侧补符号位(
正数补0负数补1
),为算术位移
- 任何位与
1
位与无变化
,与0
位与变成0
- 任何位与
1
位或变成1
,与0
位或无变化
- 任何位与
1
位异或取反
,与0位异或无变化
所以有:
- 特定位
复位0
:与0
相&
- 特定位
置位1
:与1
相|
- 特定位
取反
:与1
相^
(1)bit3~bit7
为1
,其他位为0
的二进制数
size_t ua = 0X1F << 3;
0X1F
说明这部分有5
位,分别为bit0~bit4
- 左移
3
说明这5
位变成了bit3 ~ bit7
(2)bit3~bit7
为1
,bit23~bit25
为1
,其余位为0
size_t ua = 0X1F << 3 | 0X07 << 23;
先构建特定位为1
的二进制数,再进行位取反即可
如bit3~bit7
为0
,bit23~bit25
为0
,其余位为1
:
size_t ua = ~ (0X1F << 3 | 0X07 << 23);
先看明白2.1
中的理论基础再看这个!!!
(1)给定一个无符整型数ua
,置位ua
的bit3
,保证其他位不变
ua |= (0X01 << 3);
(2)给定一个无符整型数ua
,置位ua
的bit3~bit7
,保证其他位不变
ua |= (0X1F << 3);
(1)给定一个无符整型数ua
,复位ua
的bit15
,保证其他位不变
ua &= ~(0X01 << 15);
(2)给定一个无符整型数ua
,复位ua
的bit15~bit23
,保证其他位不变
ua |= (0X1FF << 15);
给定一个无符整型数ua
,置位取出ua
的bit3~bit7
,存放在ub
中
- 先让特定位保持不变,其他位全部复位
- 再右移3位得到结果
size_t ub = ua;
ub &= (0X1F << 3);
ub >>= 3;
(1)给寄存器的bit7~bit20
赋值845
,其余位不受影响
- 先将特定位全部清零
- 再进行赋值
ua &= ~(0X3FFF << 7);
ua |= (845 << 7);
(2)给寄存器的bit7~bit20
赋值845
,同时给bit23~bit28
赋值548
,其余位不受影响
ua &= ~ ((0X3FFF << 7) | (0X3F << 23));
ua |= ((845 << 7) | (548 << 23));
(3)将寄存器bit7~bit20
中的值加上20
,其余位不受影响
- 先读出特定位的值
- 给读出的值加上特定数
- 将特定位清零
- 对特定位进行赋值
size_t ub = ua;
ub &= (0X3FFF << 7);
ub >>= 7;
ub += 20;
ua &= ~ (0X3FFF << 7);
ua |= (ub << 7);
将ua
的第bit_number + 1
位置位(第1位对应bit0,下同
)
#define SET_BIT_NUMBER(UA, BIT_NUMBER) (\
UA | ((typeof (UA))1U << BIT_NUMBER))
将ua
的第bit_number + 1
位复位
#define RESET_BIT_NUMBER(UA, BIT_NUMBER)(\
UA & ~ ((typeof (UA))1U << BIT_NUMBER))
将ua
的bit_m + 1
位到bit_n + 1
位置位
首先需要N = bit_n - bit_m + 1个1
- 得到一个全1的数:
~ (0U)
- 左移N位得到N个0:
~ (0U) << N
- 再进行取反即得到N个1:
~ (~ (0U) << N)
再左移bit_m
位再与原数位或运算即可
#define SET_BITS_M_N(UA, BIT_M, BIT_N) (\
UA | (~ (~ ((typeof (UA))0U) << (\
BIT_N - BIT_M + 1)) << BIT_M))
将ua
的bit_m + 1
位到bit_n + 1
位复位
这个和置位差不多,只是最后一步运算不同而已
#define RESET_BITS_M_N(UA, BIT_M, BIT_N)(\
UA & ~ (~ (~ ((typeof (UA))0U) << (\
BIT_N - BIT_M + 1)) << BIT_M))
将ua
的bit_m + 1
位到bit_n + 1
位取出
先将其他位复位,再右移即可
- 和3.3一样先得到N个1:
~ (~ (0U) << N)
- 左移
bit_m
位并与ua
相与
UA & ~ (~ (0U) << N) << BIT_M
- 再右移即可
#define GETBITS_N_M(UA, BIT_M, BIT_N) (\
(UA & ~ (~ ((typeof (UA))0U) << (\
BIT_N - BIT_M + 1)) << BIT_M) >> BIT_M)
#include
#define SET_BIT_NUMBER(UA, BIT_NUMBER) (\
UA | ((typeof (UA))1U << BIT_NUMBER))
#define RESET_BIT_NUMBER(UA, BIT_NUMBER)(\
UA & ~ ((typeof (UA))1U << BIT_NUMBER))
#define SET_BITS_M_N(UA, BIT_M, BIT_N) (\
UA | (~ (~ ((typeof (UA))0U) << (\
BIT_N - BIT_M + 1)) << BIT_M))
#define RESET_BITS_M_N(UA, BIT_M, BIT_N)(\
UA & ~ (~ (~ ((typeof (UA))0U) << (\
BIT_N - BIT_M + 1)) << BIT_M))
#define GETBITS_N_M(UA, BIT_M, BIT_N) (\
(UA & ~ (~ ((typeof (UA))0U) << (\
BIT_N - BIT_M + 1)) << BIT_M) >> BIT_M)
int main(void)
{
size_t UA = 0XF000F000;
printf("0X%lX\n", SET_BIT_NUMBER(UA, 3) | SET_BIT_NUMBER(UA, 4));
printf("0X%lX\n", RESET_BIT_NUMBER(UA, 3) | RESET_BIT_NUMBER(UA, 4));
printf("0X%lX\n", SET_BITS_M_N(UA, 0, 3) | SET_BITS_M_N(UA, 4, 7));
printf("0X%lX\n", RESET_BITS_M_N(UA, 12, 15) | RESET_BITS_M_N(UA, 28, 33));
printf("0X%lX\n", GETBITS_N_M(UA, 0, 15));
return 0;
}
对bit3
和 bit4
进行置位如图所示:
对bit0~3
和 bit4~7
进行置位如图所示:
我们可以看到程序的运行结果和上述分析结果是一致的