如何设置、清除和切换一点?


当前回答

展开位集答案:

#include <iostream>
#include <bitset>
#include <string>

using namespace std;
int main() {
  bitset<8> byte(std::string("10010011");

  // Set Bit
  byte.set(3); // 10010111

  // Clear Bit
  byte.reset(2); // 10010101

  // Toggle Bit
  byte.flip(7); // 00010101

  cout << byte << endl;

  return 0;
}

其他回答

比特场方法在嵌入式领域还有其他优势。您可以定义直接映射到特定硬件寄存器中的位的结构。

struct HwRegister {
    unsigned int errorFlag:1;  // one-bit flag field
    unsigned int Mode:3;       // three-bit mode field
    unsigned int StatusCode:4;  // four-bit status code
};

struct HwRegister CR3342_AReg;

您需要注意位打包顺序-我认为它首先是MSB,但这可能取决于实现。此外,验证编译器处理程序字段如何跨越字节边界。

然后,您可以像以前一样读取、写入和测试各个值。

以下是C中的一个例程,用于执行基本的逐位操作:

#define INT_BIT (unsigned int) (sizeof(unsigned int) * 8U) //number of bits in unsigned int

int main(void)
{
    
    unsigned int k = 5; //k is the bit position; here it is the 5th bit from the LSb (0th bit)
    
    unsigned int regA = 0x00007C7C; //we perform bitwise operations on regA
    
    regA |= (1U << k);    //Set kth bit
    
    regA &= ~(1U << k);   //Clear kth bit
    
    regA ^= (1U << k);    //Toggle kth bit
    
    regA = (regA << k) | regA >> (INT_BIT - k); //Rotate left by k bits
    
    regA = (regA >> k) | regA << (INT_BIT - k); //Rotate right by k bits

    return 0;   
}

我使用头文件中定义的宏来处理位集和清除:

/* a=target variable, b=bit number to act upon 0-n */
#define BIT_SET(a,b) ((a) |= (1ULL<<(b)))
#define BIT_CLEAR(a,b) ((a) &= ~(1ULL<<(b)))
#define BIT_FLIP(a,b) ((a) ^= (1ULL<<(b)))
#define BIT_CHECK(a,b) (!!((a) & (1ULL<<(b))))        // '!!' to make sure this returns 0 or 1

#define BITMASK_SET(x, mask) ((x) |= (mask))
#define BITMASK_CLEAR(x, mask) ((x) &= (~(mask)))
#define BITMASK_FLIP(x, mask) ((x) ^= (mask))
#define BITMASK_CHECK_ALL(x, mask) (!(~(x) & (mask)))
#define BITMASK_CHECK_ANY(x, mask) ((x) & (mask))

尝试使用C语言中的以下函数之一更改n位:

char bitfield;

// Start at 0th position

void chang_n_bit(int n, int value)
{
    bitfield = (bitfield | (1 << n)) & (~( (1 << n) ^ (value << n) ));
}

Or

void chang_n_bit(int n, int value)
{
    bitfield = (bitfield | (1 << n)) & ((value << n) | ((~0) ^ (1 << n)));
}

Or

void chang_n_bit(int n, int value)
{
    if(value)
        bitfield |= 1 << n;
    else
        bitfield &= ~0 ^ (1 << n);
}

char get_n_bit(int n)
{
    return (bitfield & (1 << n)) ? 1 : 0;
}

如何设置、清除和切换单个位?

要解决试图形成掩码时的常见编码陷阱,请执行以下操作:1并不总是足够宽

当数字的类型大于1时会出现什么问题?x对于移位1<<x可能太大,导致未定义的行为(UB)。即使x不太大,~也可能无法翻转足够多的最高有效位。

// assume 32 bit int/unsigned
unsigned long long number = foo();

unsigned x = 40; 
number |= (1 << x);  // UB
number ^= (1 << x);  // UB
number &= ~(1 << x); // UB

x = 10;
number &= ~(1 << x); // Wrong mask, not wide enough

要确保1足够宽:

代码可以使用1ull或pedatically(uintmax_t)1并让编译器进行优化。

number |= (1ull << x);
number |= ((uintmax_t)1 << x);

或铸造-这使得编码/审查/维护问题保持铸造正确和最新。

number |= (type_of_number)1 << x;

或者通过强制一个至少与数字类型一样宽的数学运算来温和地推广1。

number |= (number*0 + 1) << x;

与大多数位操作一样,最好使用无符号类型而不是有符号类型