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

C++ 如何设置、清除和切换单个位?,c++,c,bit-manipulation,bitwise-operators,C++,C,Bit Manipulation,Bitwise Operators,如何设置、清除和切换一点?设置一点 使用按位OR运算符(|)设置位 number |= 1UL << n; 这将清除编号的第位。必须使用按位NOT运算符(~)反转位字符串,然后将其反转 切换一点 异或运算符(^)可用于切换位 number ^= 1UL << n; 这将把nnumber的第位的值放入变量bit 将第n位更改为x 将2版的补码C++实现为< n>代码>第1位> > 或 0 >代码>: number ^= (-x ^ number) & (1U

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

设置一点 使用按位OR运算符(
|
)设置位

number |= 1UL << n;
这将清除编号的第位。必须使用按位NOT运算符(
~
)反转位字符串,然后将其反转

切换一点 异或运算符(
^
)可用于切换位

number ^= 1UL << n;
这将把
n
number的第位的值放入变量
bit

将第n位更改为x

将2版的补码C++实现为< <代码> n>代码>第1位> <代码> > <代码>或<代码> 0 >代码>:

number ^= (-x ^ number) & (1UL << n);

unsigned long newbit=!!x、 //也可以布尔化为强制0或1

number^=(-newbit^number)和(1UL有时值得使用
enum
来命名位:

enum ThingFlags = {
  ThingMask  = 0x0000,
  ThingFlag0 = 1 << 0,
  ThingFlag1 = 1 << 1,
  ThingError = 1 << 8,
}
设置、清除和测试。通过这种方式,您可以对代码的其余部分隐藏神奇的数字


除此之外,我支持Jeremy的解决方案。

另一个选项是使用位字段:

struct bits {
    unsigned int a:1;
    unsigned int b:1;
    unsigned int c:1;
};

struct bits mybits;
定义一个3位字段(实际上是三个1位字段)。位操作现在变得有点(哈哈)简单了:

要设置或清除位,请执行以下操作:

mybits.b = 1;
mybits.c = 0;
BITOP(array, bit, &=~);
要切换位,请执行以下操作:

mybits.a = !mybits.a;
mybits.b = ~mybits.b;
mybits.c ^= 1;  /* all work */
BITOP(array, bit, ^=);
检查一下:

if (mybits.c)  //if mybits.c is non zero the next line below will execute
这只适用于固定大小的位字段。否则,您必须求助于前几篇文章中描述的位旋转技术。

From's bitops.h: 如果posn==8,则其计算结果为:

0000 0000 0000 0000 0000 0000 0000 0001 binary.
0000 0000 0000 0000 0000 0001 0000 0000 binary.
换句话说,它只是创建一个0的字段,在指定的位置有一个1 唯一棘手的部分是在BitClr()宏中,我们需要在其中设置 1字段中的单个0位。这是通过使用1来实现的 由波浪号(~)运算符表示的相同表达式的补码

一旦创建了掩码,它将按照您的建议应用于参数, 通过使用按位and(&)、or(|)和xor(^)运算符。由于掩码 是long类型,宏在char、short和int上同样有效, 或者长的

归根结底,这是一个解决一整类问题的通用方法 当然,重写 相当于每次使用显式掩码值时使用的任何这些宏 需要一个,但为什么要这样做?记住,宏替换发生在 预处理器等生成的代码将反映以下事实: 编译器认为它们是常量,也就是说,使用它们同样有效 每次你需要做的时候,广义的宏就可以“重新发明轮子” 位操作

不相信?这里有一些测试代码-我使用了Watcom C并进行了充分优化 并且不使用cdecl,因此产生的拆卸将尽可能干净 可能的:

----[测试C]----------------------------------------------------------------

#define BOOL(x) (!(!(x)))

#define BitSet(arg,posn) ((arg) | (1L << (posn)))
#define BitClr(arg,posn) ((arg) & ~(1L << (posn)))
#define BitTst(arg,posn) BOOL((arg) & (1L << (posn)))
#define BitFlp(arg,posn) ((arg) ^ (1L << (posn)))

int bitmanip(int word)
{
      word = BitSet(word, 2);
      word = BitSet(word, 7);
      word = BitClr(word, 3);
      word = BitFlp(word, 9);
      return word;
}
Module: C:\BINK\tst.c
Group: 'DGROUP' CONST,CONST2,_DATA,_BSS

Segment: _TEXT  BYTE   00000008 bytes  
 0000  0c 84             bitmanip_       or      al,84H    ; set bits 2 and 7
 0002  80 f4 02                          xor     ah,02H    ; flip bit 9 of EAX (bit 1 of AH)
 0005  24 f7                             and     al,0f7H
 0007  c3                                ret     

No disassembly errors

----[finis]-------------------------------------------------------------

如果你正在进行大量的位旋转,你可能需要使用掩码,这将使整个过程更快。以下函数非常快速,并且仍然灵活(它们允许在任何大小的位映射中进行位旋转)


由您来确保位号在您传递的位映射范围内。请注意,对于字节、字、DWORD、QWORD等在内存中相互正确映射的小端处理器(小端处理器比大端处理器“更好”的主要原因,啊,我感觉一场火焰战即将来临……)

< P>使用标准C++库:

或版本:

无需自行滚动:

#include <bitset>
#include <iostream>

int main()
{
    std::bitset<5> x;

    x[1] = 1;
    x[2] = 0;
    // Note x[0-4]  valid

    std::cout << x << std::endl;
}

与编译时大小的位集相比,Boost版本允许运行时大小的位集。

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

/* 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

/* x=target variable, y=mask */
#define BITMASK_SET(x,y) ((x) |= (y))
#define BITMASK_CLEAR(x,y) ((x) &= (~(y)))
#define BITMASK_FLIP(x,y) ((x) ^= (y))
#define BITMASK_CHECK_ALL(x,y) (!(~(x) & (y)))
#define BITMASK_CHECK_ANY(x,y) ((x) & (y))
/*a=目标变量,b=作用于0-n的位号*/

#定义位集合(a,b)((a)|=(1all位域方法在嵌入式领域中还有其他优势。您可以定义直接映射到特定硬件寄存器中位的结构

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优先,但这可能取决于实现。此外,请验证编译器处理程序字段如何跨越字节边界

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

检查任意类型变量中任意位置的位: 示例用法:

int main(void)
{
    unsigned char arr[8] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF };

    for (int ix = 0; ix < 64; ++ix)
        printf("bit %d is %d\n", ix, bit_test(arr, ix));

    return 0;
}
int main(无效)
{
无符号字符arr[8]={0x01、0x23、0x45、0x67、0x89、0xAB、0xCD、0xEF};
对于(int-ix=0;ix<64;++ix)
printf(“位%d是%d\n”,ix,位测试(arr,ix));
返回0;
}
注意事项: 这是为了快速而设计的(考虑到它的灵活性)和非branchy。在编译Sun Studio 8时,它产生了高效的SPARC机器代码;我还使用MSVC++2008在amd64上对其进行了测试。可以制作类似的宏来设置和清除位。与其他许多解决方案相比,此解决方案的关键区别在于,它适用于几乎任何类型变量中的任何位置

使用以下命令:

int ToggleNthBit ( unsigned char n, int num )
{
    if(num & (1 << n))
        num &= ~(1 << n);
    else
        num |= (1 << n);

    return num;
}
int-ToggleNthBit(无符号字符n,int-num)
{

如果(num&(1更一般,对于任意大小的位图:

#define BITS 8
#define BIT_SET(  p, n) (p[(n)/BITS] |=  (0x80>>((n)%BITS)))
#define BIT_CLEAR(p, n) (p[(n)/BITS] &= ~(0x80>>((n)%BITS)))
#define BIT_ISSET(p, n) (p[(n)/BITS] &   (0x80>>((n)%BITS)))

下面是我最喜欢的位算术宏,它适用于任何类型的无符号整数数组,从
无符号字符
大小
(这是最有效的类型):

要清除一点:

mybits.b = 1;
mybits.c = 0;
BITOP(array, bit, &=~);
要切换位,请执行以下操作:

mybits.a = !mybits.a;
mybits.b = ~mybits.b;
mybits.c ^= 1;  /* all work */
BITOP(array, bit, ^=);
要测试一点:

if (BITOP(array, bit, &)) ...

等等。

此程序用于将任何数据位从0更改为1或从1更改为0:

{
    unsigned int data = 0x000000F0;
    int bitpos = 4;
    int bitvalue = 1;
    unsigned int bit = data;
    bit = (bit>>bitpos)&0x00000001;
    int invbitvalue = 0x00000001&(~bitvalue);
    printf("%x\n",bit);

    if (bitvalue == 0)
    {
        if (bit == 0)
            printf("%x\n", data);
        else
        {
             data = (data^(invbitvalue<<bitpos));
             printf("%x\n", data);
        }
    }
    else
    {
        if (bit == 1)
            printf("elseif %x\n", data);
        else
        {
            data = (data|(bitvalue<<bitpos));
            printf("else %x\n", data);
        }
    }
}
{
无符号整数数据=0x000000F0;
int-bitpos=4;
int比特值=1;
无符号整数位=数据;
位=(位>>位位置)&0x00000001;
int invbitvalue=0x00000001&(~bitvalue);
printf(“%x\n”,位);
如果(位值==0)
{
如果(位==0)
printf(“%x\n”,数据);
其他的
{

data=(data^(invbitvalue对于初学者,我想再解释一下
int main(void)
{
    unsigned char arr[8] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF };

    for (int ix = 0; ix < 64; ++ix)
        printf("bit %d is %d\n", ix, bit_test(arr, ix));

    return 0;
}
int ToggleNthBit ( unsigned char n, int num )
{
    if(num & (1 << n))
        num &= ~(1 << n);
    else
        num |= (1 << n);

    return num;
}
#define BITS 8
#define BIT_SET(  p, n) (p[(n)/BITS] |=  (0x80>>((n)%BITS)))
#define BIT_CLEAR(p, n) (p[(n)/BITS] &= ~(0x80>>((n)%BITS)))
#define BIT_ISSET(p, n) (p[(n)/BITS] &   (0x80>>((n)%BITS)))
#define BITOP(a,b,op) \
 ((a)[(size_t)(b)/(8*sizeof *(a))] op ((size_t)1<<((size_t)(b)%(8*sizeof *(a)))))
BITOP(array, bit, |=);
BITOP(array, bit, &=~);
BITOP(array, bit, ^=);
if (BITOP(array, bit, &)) ...
{
    unsigned int data = 0x000000F0;
    int bitpos = 4;
    int bitvalue = 1;
    unsigned int bit = data;
    bit = (bit>>bitpos)&0x00000001;
    int invbitvalue = 0x00000001&(~bitvalue);
    printf("%x\n",bit);

    if (bitvalue == 0)
    {
        if (bit == 0)
            printf("%x\n", data);
        else
        {
             data = (data^(invbitvalue<<bitpos));
             printf("%x\n", data);
        }
    }
    else
    {
        if (bit == 1)
            printf("elseif %x\n", data);
        else
        {
            data = (data|(bitvalue<<bitpos));
            printf("else %x\n", data);
        }
    }
}
value is 0x55;
bitnum : 3rd.
0101 0101
&
0000 1000
___________
0000 0000 (mean 0: False). It will work fine if the third bit is 1 (then the answer will be True)
0101 0101
^
0000 1000
___________
0101 1101 (Flip the third bit without affecting other bits)
0101 0101
|
0000 1000
___________
0101 1101 (set the third bit without affecting other bits)
bool    IsGph[256], IsNotGph[256];

//  Initialize boolean array to detect printable characters
for(i=0; i<sizeof(IsGph); i++)  {
    IsGph[i] = isgraph((unsigned char)i);
}
//  Initialize boolean array to detect UN-printable characters, 
//  then call function to toggle required bits true, while initializing a 2nd
//  boolean array as the complement of the 1st.
for(i=0; i<sizeof(IsGph); i++)  {
    if(IsGph[i])    {
         IsNotGph[i] = 0;
    }   else   {
         IsNotGph[i] = 1;
    }
}
#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;
}
char bitfield;

// Start at 0th position

void chang_n_bit(int n, int value)
{
    bitfield = (bitfield | (1 << n)) & (~( (1 << n) ^ (value << n) ));
}
void chang_n_bit(int n, int value)
{
    bitfield = (bitfield | (1 << n)) & ((value << n) | ((~0) ^ (1 << n)));
}
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;
}
SET_FLAG(Status, Flag)            ((Status) |= (Flag))
CLEAR_FLAG(Status, Flag)          ((Status) &= ~(Flag))
INVALID_FLAGS(ulFlags, ulAllowed) ((ulFlags) & ~(ulAllowed))
TEST_FLAGS(t,ulMask, ulBit)       (((t)&(ulMask)) == (ulBit))
IS_FLAG_SET(t,ulMask)             TEST_FLAGS(t,ulMask,ulMask)
IS_FLAG_CLEAR(t,ulMask)           TEST_FLAGS(t,ulMask,0)
set_bit  Atomically set a bit in memory
clear_bit  Clears a bit in memory
change_bit  Toggle a bit in memory
test_and_set_bit  Set a bit and return its old value
test_and_clear_bit  Clear a bit and return its old value
test_and_change_bit  Change a bit and return its old value
test_bit  Determine whether a bit is set
// 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
number |= (1ull << x);
number |= ((uintmax_t)1 << x);
number |= (type_of_number)1 << x;
number |= (number*0 + 1) << x;
int set_nth_bit(int num, int n){    
    return (num | 1 << n);
}

int clear_nth_bit(int num, int n){    
    return (num & ~( 1 << n));
}

int toggle_nth_bit(int num, int n){    
    return num ^ (1 << n);
}

int check_nth_bit(int num, int n){    
    return num & (1 << n);
}
bit = (num >> n) & 1;
       0011 0111 (55 in decimal)
    >>         4 (right shift 4 times)
-----------------
       0000 0011
     & 0000 0001 (1 in decimal)
-----------------
    => 0000 0001 (final result)
num |= (1 << n);    // Equivalent to; num = (1 << n) | num;
       0000 0001 (1 in decimal)
    <<         4 (left shift 4 times)
-----------------
       0001 0000
     | 0011 0111 (55 in decimal)
-----------------
    => 0001 0000 (final result)
num &= (~(1 << n));    // Equivalent to; num = num & (~(1 << n));
       0000 0001 (1 in decimal)
    <<         4 (left shift 4 times)
-----------------
     ~ 0001 0000
-----------------
       1110 1111
     & 0011 0111 (55 in decimal)
-----------------
    => 0010 0111 (final result)
num ^= (1 << n);    // Equivalent to; num = num ^ (1 << n);
       0000 0001 (1 in decimal)
    <<         4 (left shift 4 times)
-----------------
       0001 0000
     ^ 0011 0111 (55 in decimal)
-----------------
    => 0010 0111 (final result)
public class BitwiseOperations {

    public static void main(String args[]) {

        setABit(0, 4); // set the 4th bit, 0000 -> 1000 [8]
        clearABit(16, 5); // clear the 5th bit, 10000 -> 00000 [0]
        toggleABit(8, 4); // toggle the 4th bit, 1000 -> 0000 [0]
        checkABit(8,4); // check the 4th bit 1000 -> true 
    }

    public static void setABit(int input, int n) {
        input = input | ( 1 << n-1);
        System.out.println(input);
    }


    public static void clearABit(int input, int n) {
        input = input & ~(1 << n-1);
        System.out.println(input);
    }

    public static void toggleABit(int input, int n) {
        input = input ^ (1 << n-1);
        System.out.println(input);
    }

    public static void checkABit(int input, int n) {
        boolean isSet = ((input >> n-1) & 1) == 1; 
        System.out.println(isSet);
    }
}


Output :
8
0
0
true
number = (((number | (1 << n)) ^ (1 << n))) | (x << n);
#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;   
}