按位运算符在C中的应用及其效率?

Sai*_*ali 9 c bitwise-operators masking

我是bitwise运算符的新手.

我理解逻辑函数如何工作以获得最终结果.例如,当你按位AND两个数字,最后的结果将是在AND这两个数值(1 & 0 = 0; 1 & 1 = 1; 0 & 0 = 0).与OR,相同XOR,和NOT.

我不明白的是他们的应用.我试着到处寻找,其中大多数只是解释按位操作是如何工作的.在所有按位运算符中,我只理解移位运算符的应用(乘法和除法).我也遇到了掩蔽.我知道屏蔽是按位进行的,AND但究竟是什么目的以及我在何处以及如何使用它?

你能详细说明我如何使用遮蔽吗?对于有类似用途ORXOR

jxh*_*jxh 17

按位运算符的低级用例是执行基数2数学运算.有一个众所周知的技巧来测试一个数字是2的幂:

if ((x & (x - 1)) == 0) {
    printf("%d is a power of 2\n", x);
}
Run Code Online (Sandbox Code Playgroud)

但是,它也可以提供更高级别的功能:设置操作.您可以将一组位集合视为一组.为了解释,让一个字节中的每个位代表8个不同的项目,比如我们太阳系中的行星(冥王星不再被认为是行星,所以8就足够了!):

#define Mercury (1 << 0)
#define Venus   (1 << 1)
#define Earth   (1 << 2)
#define Mars    (1 << 3)
#define Jupiter (1 << 4)
#define Saturn  (1 << 5)
#define Uranus  (1 << 6)
#define Neptune (1 << 7)
Run Code Online (Sandbox Code Playgroud)

然后,我们可以形成一个行星(一个子集)的集合,就像使用|:

unsigned char Giants = (Jupiter|Saturn|Uranus|Neptune);
unsigned char Visited = (Venus|Earth|Mars);
unsigned char BeyondTheBelt = (Jupiter|Saturn|Uranus|Neptune);
unsigned char All = (Mercury|Venus|Earth|Mars|Jupiter|Saturn|Uranus|Neptune);
Run Code Online (Sandbox Code Playgroud)

现在,您可以使用a &来测试两个集合是否有交集:

if (Visited & Giants) {
    puts("we might be giants");
}
Run Code Online (Sandbox Code Playgroud)

^操作通常用于查看两个集合之间的不同(集合的并集减去它们的交集):

if (Giants ^ BeyondTheBelt) {
    puts("there are non-giants out there");
}
Run Code Online (Sandbox Code Playgroud)

所以,把它|看作联合,&作为交集,^作为联合减去交集.

一旦你购买代表一个集合的位的想法,那么按位操作自然会帮助操纵这些集合.


Joh*_*136 1

实施例1

如果你有 10 个“协同工作”的布尔值,你就可以大大简化你的代码。

int B1 = 0x01;
int B2 = 0x02;
int B10 = 0x0A;

int someValue = get_a_value_from_somewhere();

if (someValue & (B1 + B10)) {
    // B1 and B10 are set
}
Run Code Online (Sandbox Code Playgroud)

实施例2

与硬件接口。硬件上的地址可能需要位级访问来控制接口。例如,缓冲区上的溢出位或状态字节可以告诉您 8 个不同事物的状态。使用位掩码,您可以获取所需的实际信息位。

if (register & 0x80) {
    // top bit in the byte is set which may have special meaning.
}
Run Code Online (Sandbox Code Playgroud)

这实际上只是示例 1 的一个特例。