比特移位及其逻辑运算符

Bit shifts and their logical operators

本文关键字:逻辑运算符      更新时间:2023-10-16

下面的这个程序将最后一个(初级)和倒数第二个字节的变量i输入int。我试图理解程序员为什么写这个

i = (i & LEADING_TWO_BYTES_MASK) | ((i & PENULTIMATE_BYTE_MASK) >> 8) | ((i & LAST_BYTE_MASK) << 8);

有人能用通俗易懂的英语向我解释一下下面的节目吗。

#include <stdio.h>
#include <cstdlib>
#define LAST_BYTE_MASK 255 //11111111
#define PENULTIMATE_BYTE_MASK 65280 //1111111100000000
#define LEADING_TWO_BYTES_MASK 4294901760 //11111111111111110000000000000000

int main(){
    unsigned int i = 0;
    printf("i = ");
    scanf("%d", &i);
    i = (i & LEADING_TWO_BYTES_MASK) | ((i & PENULTIMATE_BYTE_MASK) >> 8) | ((i & LAST_BYTE_MASK) << 8);
    printf("i = %d", i);
    system("pause");
}

既然你要求简明英语:他交换整数的第一个和第二个字节。

这个表达式确实有点复杂,但本质上作者是这样做的:

// Mask out relevant bytes
unsigned higher_order_bytes = i & LEADING_TWO_BYTES_MASK;
unsigned first_byte = i & LAST_BYTE_MASK;
unsigned second_byte = i & PENULTIMATE_BYTE_MASK;
// Switch positions:
unsigned first_to_second = first_byte << 8;
unsigned second_to_first = second_byte >> 8;
// Concatenate back together:
unsigned result = higher_order_bytes | first_to_second | second_to_first;

顺便说一句,使用十六进制表示法定义掩码比使用十进制更可读。此外,在这里使用#define是错误的。C和C++都有const:

unsigned const LEADING_TWO_BYTES_MASK = 0xFFFF0000;
unsigned const PENULTIMATE_BYTE_MASK = 0xFF00;
unsigned const LAST_BYTE_MASK = 0xFF;

要理解此代码,您需要了解&|和位偏移在位级别上的作用。

用十六进制而不是十进制定义掩码更具指导意义,因为它们直接对应于二进制表示,并且很容易看到哪些位是开和关的:

#define LAST 0xFF          // all bits in the first byte are 1
#define PEN 0xFF00         // all bits in the second byte are 1
#define LEAD 0xFFFF0000    // all bits in the third and fourth bytes are 1 

然后

i = (i & LEAD)             // leave the first 2 bytes of the 32-bit integer the same
    | ((i & PEN) >> 8)     // take the 3rd byte and shift it 8 bits right
    | ((i & LAST) << 8)    // take the 4th byte and shift it 8 bits left 
    );

因此,表达式交换两个最低有效字节,同时保持两个最高有效字节不变。