首页 > 解决方案 > 为什么位移在 C 中是这样写的?

问题描述

也许这个问题会有点愚蠢,但我想知道为什么如果我们想在寄存器的某个特定位置写 0,我们必须这样写:

PORTB &= ~(1 << 2);

而不是这样(因为它不起作用):

PORTB &= (0 << 2);

0 在这里是否意味着像 0b00000000 (对于 8 位寄存器)?

标签: cembedded

解决方案


让我们逐步分解:

// PORTB &= ~(1 << 2);

int bit_position = 2;
int bit_mask = 1;              // = 0000 0001
bit_mask <<= bit_position;     // = 0000 0100
int inverted_mask = ~bit_mask; // = 1111 1011

int PORTB = 0x77;              //   0111 0111
PORTB &= inverted_mask;        // & 1111 1011
                               // = 0111 0011

而且,您建议的替代方案:

// PORTB &= (0 << 2);

int bit_position = 2;
int bit_mask = 0;              // = 0000 0000
bit_mask <<= bit_position;     // = 0000 0000

int PORTB = 0x77;              //   0111 0111
PORTB &= bit_mask;             // & 0000 0000
                               // = 0000 0000

关键是计算机只是对整个寄存器一个接一个地执行操作。它不知道它应该关心该数字中所有零中的特定零。因此,您不是通过“位置 2 处的零”进行与运算,而只是通过数字零进行与运算。事实上,你不只是移动一个零或一,而是整个数字。

这就是为什么要将特定位设置为零的原因,我们必须与一个掩码进行与,该掩码在除我们希望为零的位置之外的每个位置都有一个。(与 1 进行与运算不会更改位,而与 0 进行与运算使其为零。)


推荐阅读