位操作,不必要的掩码?
Bit manipulation, unnecessary mask?
我正在尝试掌握嵌入式 C 编程中的位操作。
我有以下代码
#define X_POS (8UL)
#define X_MASK (0x1FUL<<X_POS)
#define Y_POS (16UL)
#define Y_MASK (0x3UL<<Y_POS)
typedef struct {
uint32_t res[6];
uint32_t config[10];
} myStruct_type;
myStruct_type myStruct;
void configure (uint32_t n, uint32_t x, uint32_t y)
{
myStruct.config[n] &= ~(X_MASK | Y_MASK); // A
myStruct.config[n] |= ((x<<X_POS) & X_MASK) | ((y<<Y_POS) & Y_MASK); // B
}
int main (void)
{
configure(3, 18, 2);
while (1) { }
}
我理解注释A行是用来将感兴趣的位设置为0,即清除位。
我还了解到,在标有 B 的行上,感兴趣的位被设置为想要的值。
但是 B 行的 X_MASK 和 Y_MASK 的目的是什么???
设置的值不是
(x<<X_POS) | (y<<Y_POS)
B 行屏蔽的目的是确保只设置您想要设置的位。例如如果 x 是 0xFFFFFFFF
,&
和 X_MASK
将停止设置您感兴趣的位以上的位。
所以假设 config[0] 从 0 开始,x 是 0xFFFFFFFF 并且 y 是 0,如果没有 maskingin 行 B,你会得到
myStruct.config[0] &= ~(X_MASK | Y_MASK); // config[0] is still 0
myStruct.config[0] |= (0xFFFFFFFF << 8) | (0<< 16);
// config[0] is now 0xFFFFFF00
加上口罩,第二行是
myStruct.config[0] |= ((0xFFFFFFFF<< 8) & 0x1F00) | (( 0 << 16) & 3 << 16); // B
也就是
myStruct.config[0] |= 0x1F00 | 0);
如果您只使用 (x<<X_POS) | (y<<Y_POS)
,您只需将值 x
和 y
移到左侧即可。
掩码消除了不需要的位。例如:
X_MASK = 0x1FUL << 8UL = 0x1F00000000 = 0b111110000...
使用逻辑 & (AND),您将掩码上为零的所有位设置为零:
X_MASK 0b00000001111100000000.....
x<<X_POS 0b01010101010100000000.....
& ________________________
result 0b00000001010100000000.....
在更高层次上,您可以说,X_MASK
将 x
的所有位设置为零,最低 5 位除外,而 Y_MASK
将 [=14= 的所有位设置为零] 到零,除了最低的 2。之后你的结果会向左移动。所以掩码会清除高位。
我正在尝试掌握嵌入式 C 编程中的位操作。
我有以下代码
#define X_POS (8UL)
#define X_MASK (0x1FUL<<X_POS)
#define Y_POS (16UL)
#define Y_MASK (0x3UL<<Y_POS)
typedef struct {
uint32_t res[6];
uint32_t config[10];
} myStruct_type;
myStruct_type myStruct;
void configure (uint32_t n, uint32_t x, uint32_t y)
{
myStruct.config[n] &= ~(X_MASK | Y_MASK); // A
myStruct.config[n] |= ((x<<X_POS) & X_MASK) | ((y<<Y_POS) & Y_MASK); // B
}
int main (void)
{
configure(3, 18, 2);
while (1) { }
}
我理解注释A行是用来将感兴趣的位设置为0,即清除位。
我还了解到,在标有 B 的行上,感兴趣的位被设置为想要的值。
但是 B 行的 X_MASK 和 Y_MASK 的目的是什么???
设置的值不是(x<<X_POS) | (y<<Y_POS)
B 行屏蔽的目的是确保只设置您想要设置的位。例如如果 x 是 0xFFFFFFFF
,&
和 X_MASK
将停止设置您感兴趣的位以上的位。
所以假设 config[0] 从 0 开始,x 是 0xFFFFFFFF 并且 y 是 0,如果没有 maskingin 行 B,你会得到
myStruct.config[0] &= ~(X_MASK | Y_MASK); // config[0] is still 0
myStruct.config[0] |= (0xFFFFFFFF << 8) | (0<< 16);
// config[0] is now 0xFFFFFF00
加上口罩,第二行是
myStruct.config[0] |= ((0xFFFFFFFF<< 8) & 0x1F00) | (( 0 << 16) & 3 << 16); // B
也就是
myStruct.config[0] |= 0x1F00 | 0);
如果您只使用 (x<<X_POS) | (y<<Y_POS)
,您只需将值 x
和 y
移到左侧即可。
掩码消除了不需要的位。例如:
X_MASK = 0x1FUL << 8UL = 0x1F00000000 = 0b111110000...
使用逻辑 & (AND),您将掩码上为零的所有位设置为零:
X_MASK 0b00000001111100000000.....
x<<X_POS 0b01010101010100000000.....
& ________________________
result 0b00000001010100000000.....
在更高层次上,您可以说,X_MASK
将 x
的所有位设置为零,最低 5 位除外,而 Y_MASK
将 [=14= 的所有位设置为零] 到零,除了最低的 2。之后你的结果会向左移动。所以掩码会清除高位。