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

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

1546107 次浏览

设置一点

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

number |= 1UL << n;

这将设置numbern位。n应该是零,如果你想设置1位,以此类推直到n-1,如果你想设置n位。

如果numberunsigned long宽,则使用1ULL1UL << n的提升直到评估1UL << n之后才会发生,其中未定义的行为是移动超过long的宽度。这同样适用于所有其他示例。

清理一下

使用按位AND运算符(&)清除位。

number &= ~(1UL << n);

这将清除numbern位。您必须使用按位非运算符(~)反转位字符串,然后AND它。

切换了一下

XOR运算符(^)可用于切换位。

number ^= 1UL << n;

这将切换numbern位。

查了一下

你没有要求这个,但我不妨添加它。

要检查位,请将数字n向右移动,然后按位AND它:

bit = (number >> n) & 1U;

这将把number的第n位的值放入变量bit

n位更改为x

n位设置为10可以通过以下方式实现2的补码C++实现:

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

如果x1,比特n将被设置,如果x0,比特n将被清除。如果x有其他值,您将得到垃圾。x = !!x将布尔化为0或1。

要使其独立于2的补码否定行为(其中-1设置了所有位,与1的补码或符号/大小C++实现不同),请使用无符号否定。

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

unsigned long newbit = !!x;    // Also booleanize to force 0 or 1number ^= (-newbit ^ number) & (1UL << n);

使用无符号类型进行可移植位操作通常是个好主意。

number = (number & ~(1UL << n)) | (x << n);

(number & ~(1UL << n))将清除n位,(x << n)n位设置为x

一般来说,不复制/粘贴代码也是一个好主意,很多人使用预处理器宏(如社区wiki进一步回答)或某种封装。

有时值得使用enum姓名位:

enum ThingFlags = {ThingMask  = 0x0000,ThingFlag0 = 1 << 0,ThingFlag1 = 1 << 1,ThingError = 1 << 8,}

然后稍后使用名字。即。写

thingstate |= ThingFlag1;thingstate &= ~ThingFlag0;if (thing & ThingError) {...}

设置、清除和测试。通过这种方式,您可以从其余代码中隐藏魔法数字。

除此之外,我支持Paige Ruten的解决方案

另一种选择是使用位字段:

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;

切换一下:

mybits.a = !mybits.a;mybits.b = ~mybits.b;mybits.c ^= 1;  /* all work */

检查一下:

if (mybits.c)  //if mybits.c is non zero the next line below will execute

这只适用于固定大小的位域。否则你必须求助于历史发文中描述的位摆弄技术。

snip-c.zip的bitops. h:

/***  Bit set, clear, and test operations****  public domain snippet by Bob Stout*/
typedef enum {ERROR = -1, FALSE, TRUE} LOGICAL;
#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)))

好,我们来分析一下…

在所有这些中,您似乎遇到的常见表达式是“(1L<<(posn))”。这一切所做的只是创建一个具有单个位的掩码并且适用于任何整数类型。“posn”参数指定您想要位的位置。如果posn==0,则此表达式将评估到:

0000 0000 0000 0000 0000 0000 0000 0001 binary.

如果posn==8,它将计算为:

0000 0000 0000 0000 0000 0001 0000 0000 binary.

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

一旦创建了掩码,它就会按照您的建议应用于参数,通过使用按位和(&)、或(|)和xor(^)运算符。由于掩码是long类型的,宏也可以在char's、短的、int's、长的

底线是这是整个类的通用解决方案当然,这是可能的,甚至是适当的重写等效于每次您使用显式掩码值的任何这些宏需要一个,但为什么要这样做?记住,宏替换发生在预处理器,因此生成的代码将反映值的事实被编译器视为常量-即使用它同样有效广义宏“重新发明轮子”每次你需要做的位操作。

不服气?这是一些测试代码-我使用了完全优化的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.cGroup: 'DGROUP' CONST,CONST2,_DATA,_BSS
Segment: _TEXT  BYTE   00000008 bytes0000  0c 84             bitmanip_       or      al,84H    ; set bits 2 and 70002  80 f4 02                          xor     ah,02H    ; flip bit 9 of EAX (bit 1 of AH)0005  24 f7                             and     al,0f7H0007  c3                                ret
No disassembly errors

----[结束 ]-----------------------------------------------------------------

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

const unsigned char TQuickByteMask[8] ={0x01, 0x02, 0x04, 0x08,0x10, 0x20, 0x40, 0x80,};

/** Set bit in any sized bit mask.** @return    none** @param     bit    - Bit number.* @param     bitmap - Pointer to bitmap.*/void TSetBit( short bit, unsigned char *bitmap){short n, x;
x = bit / 8;        // Index to byte.n = bit % 8;        // Specific bit in byte.
bitmap[x] |= TQuickByteMask[n];        // Set bit.}

/** Reset bit in any sized mask.** @return  None** @param   bit    - Bit number.* @param   bitmap - Pointer to bitmap.*/void TResetBit( short bit, unsigned char *bitmap){short n, x;
x = bit / 8;        // Index to byte.n = bit % 8;        // Specific bit in byte.
bitmap[x] &= (~TQuickByteMask[n]);    // Reset bit.}

/** Toggle bit in any sized bit mask.** @return   none** @param   bit    - Bit number.* @param   bitmap - Pointer to bitmap.*/void TToggleBit( short bit, unsigned char *bitmap){short n, x;
x = bit / 8;        // Index to byte.n = bit % 8;        // Specific bit in byte.
bitmap[x] ^= TQuickByteMask[n];        // Toggle bit.}

/** Checks specified bit.** @return  1 if bit set else 0.** @param   bit    - Bit number.* @param   bitmap - Pointer to bitmap.*/short TIsBitSet( short bit, const unsigned char *bitmap){short n, x;
x = bit / 8;    // Index to byte.n = bit % 8;    // Specific bit in byte.
// Test bit (logigal AND).if (bitmap[x] & TQuickByteMask[n])return 1;
return 0;}

/** Checks specified bit.** @return  1 if bit reset else 0.** @param   bit    - Bit number.* @param   bitmap - Pointer to bitmap.*/short TIsBitReset( short bit, const unsigned char *bitmap){return TIsBitSet(bit, bitmap) ^ 1;}

/** Count number of bits set in a bitmap.** @return   Number of bits set.** @param    bitmap - Pointer to bitmap.* @param    size   - Bitmap size (in bits).** @note    Not very efficient in terms of execution speed. If you are doing*        some computationally intense stuff you may need a more complex*        implementation which would be faster (especially for big bitmaps).*        See (http://graphics.stanford.edu/~seander/bithacks.html).*/int TCountBits( const unsigned char *bitmap, int size){int i, count = 0;
for (i=0; i<size; i++)if (TIsBitSet(i, bitmap))count++;
return count;}

请注意,要在16位整数中设置位'n',请执行以下操作:

TSetBit( n, &my_int);

由你来确保位数在你传递的位映射的范围内。请注意,对于字节、单词、dword、qword等的小端处理器,在内存中正确映射(小端处理器比大端处理器更好的主要原因,啊,我觉得一场火焰大战即将到来…)。

使用标准C++库:#0

或者Boost版本:#0

没有必要自己动手:

#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;}

[Alpha:] > ./a.out00010

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
#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))

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

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

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

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

检查任意类型变量中任意位置的位:

#define bit_test(x, y)  ( ( ((const char*)&(x))[(y)>>3] & 0x80 >> ((y)&0x07)) >> (7-((y)&0x07) ) )

样品用法:

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;}

注释:这被设计成快速(考虑到它的灵活性)和非分支。当编译Sun Studio 8时,它会产生高效的SPARC机器代码;我还在amd64上使用MSVC++2008对它进行了测试。可以制作类似的宏来设置和清除位。与这里的许多其他解决方案相比,这个解决方案的关键区别在于它适用于几乎任何类型的变量的任何位置。

使用这个:

int ToggleNthBit ( unsigned char n, int num ){if(num & (1 << n))num &= ~(1 << n);elsenum |= (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)))

这是我最喜欢的位算术宏,它适用于从unsigned charsize_t的任何类型的无符号整数数组(这是应该有效使用的最大类型):

#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, &)) ...

该程序将任何数据位从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);}}}

对于初学者,我想用一个例子来解释一下:

示例:

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)

由于这被标记为“嵌入式”,我假设您使用的是微控制器。所有上述建议都是有效的&工作(读-修改-写、联合、结构等)。

然而,在一次基于示波器的调试中,我惊讶地发现,与直接将值写入微型的PORTnSET/PORTnCLEAR寄存器相比,这些方法在CPU周期方面有相当大的开销,这在有紧循环/高频ISR切换引脚的情况下产生了真正的差异。

对于那些不熟悉的人:在我的例子中,微型有一个通用的引脚状态寄存器PORTn,它反映了输出引脚,所以执行PORTn|=BIT_TO_SET会导致对该寄存器的读-修改-写。然而,PORTnSET/PORTnCLEAR寄存器采用“1”表示“请将此位设为1”(SET)或“请将此位设为零”(CLEAR),“0”表示“不要管引脚”。所以,你最终会得到两个端口地址,具体取决于你是设置还是清除该位(并不总是方便),但反应速度更快,组装代码更小。

Visual C 2010,也许还有许多其他编译器,都直接支持内置的布尔运算。一位有两个可能的值,就像布尔一样,所以我们可以使用布尔值代替-即使它们在这种表示中占用的空间比内存中的一位多。这是有效的,即使sizeof()运算符也能正常工作。

bool    IsGph[256], IsNotGph[256];
//  Initialize boolean array to detect printable charactersfor(i=0; i<sizeof(IsGph); i++)  {IsGph[i] = isgraph((unsigned char)i);}

所以,对于你的问题,IsGph[i] =1IsGph[i] =0使设置和清除布尔很容易。

查找不可打印的字符:

//  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;}}

请注意,这段代码没有什么“特殊”之处。它有点像一个整数-从技术上讲,它是。一个1位整数,可以保存2个值,并且只能保存2个值。

我曾经使用这种方法来查找重复的贷款记录,其中loan_number是ISAM密钥,使用6位贷款编号作为位数组的索引。非常快,8个月后,证明我们获取数据的大型机系统实际上出现了故障。位数组的简单性使得对其正确性的信心非常高-例如与搜索方法相比。

扩展到bitset答案:

#include <iostream>#include <bitset>#include <string>
using namespace std;int main() {bitset<8> byte(std::string("10010011");
// Set Bitbyte.set(3); // 10010111
// Clear Bitbyte.reset(2); // 10010101
// Toggle Bitbyte.flip(7); // 00010101
cout << byte << endl;
return 0;}

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

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;elsebitfield &= ~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)

如果您想在Linux内核中使用C编程执行所有操作,那么我建议使用Linux内核的标准API。

https://www.kernel.org/doc/htmldocs/kernel-api/ch02s03.html

set_bit  Atomically set a bit in memoryclear_bit  Clears a bit in memorychange_bit  Toggle a bit in memorytest_and_set_bit  Set a bit and return its old valuetest_and_clear_bit  Clear a bit and return its old valuetest_and_change_bit  Change a bit and return its old valuetest_bit  Determine whether a bit is set

注意:这里整个操作发生在一个步骤中。因此,即使在SMP计算机上,这些都保证为原子并且很有用保持处理器之间的一致性。

你如何设置,清除和切换一个位?

要解决尝试形成掩码时的常见编码陷阱:
1并不总是足够宽

number1更宽时会发生什么问题?
x对于1 << x导致未定义行为(UB)的移位来说可能太大了。即使x不是太大,~也可能无法翻转足够的最高有效位。

// assume 32 bit int/unsignedunsigned long long number = foo();
unsigned x = 40;number |= (1 << x);  // UBnumber ^= (1 << x);  // UBnumber &= ~(1 << x); // UB
x = 10;number &= ~(1 << x); // Wrong mask, not wide enough

要确保1足够宽:

代码可以使用1ull或迂腐地(uintmax_t)1并让编译器优化。

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

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

number |= (type_of_number)1 << x;

或者通过强制执行至少与number的类型一样宽的数学操作来温和地提升1

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

与大多数位操作一样,最好使用未签名类型而不是签署类型

模板版本(放在头文件中),支持更改多个位(适用于AVR微控制器btw):

namespace bit {template <typename T1, typename T2>constexpr inline T1 bitmask(T2 bit){return (T1)1 << bit;}template <typename T1, typename T3, typename ...T2>constexpr inline T1 bitmask(T3 bit, T2 ...bits){return ((T1)1 << bit) | bitmask<T1>(bits...);}
/** Set these bits (others retain their state) */template <typename T1, typename ...T2>constexpr inline void set (T1 &variable, T2 ...bits){variable |= bitmask<T1>(bits...);}/** Set only these bits (others will be cleared) */template <typename T1, typename ...T2>constexpr inline void setOnly (T1 &variable, T2 ...bits){variable = bitmask<T1>(bits...);}/** Clear these bits (others retain their state) */template <typename T1, typename ...T2>constexpr inline void clear (T1 &variable, T2 ...bits){variable &= ~bitmask<T1>(bits...);}/** Flip these bits (others retain their state) */template <typename T1, typename ...T2>constexpr inline void flip (T1 &variable, T2 ...bits){variable ^= bitmask<T1>(bits...);}/** Check if any of these bits are set */template <typename T1, typename ...T2>constexpr inline bool isAnySet(const T1 &variable, T2 ...bits){return variable & bitmask<T1>(bits...);}/** Check if all these bits are set */template <typename T1, typename ...T2>constexpr inline bool isSet (const T1 &variable, T2 ...bits){return ((variable & bitmask<T1>(bits...)) == bitmask<T1>(bits...));}/** Check if all these bits are not set */template <typename T1, typename ...T2>constexpr inline bool isNotSet (const T1 &variable, T2 ...bits){return ((variable & bitmask<T1>(bits...)) != bitmask<T1>(bits...));}}

使用示例:

#include <iostream>#include <bitset> // for console output of binary values
// and include the code above of course
using namespace std;
int main() {uint8_t v = 0b1111'1100;bit::set(v, 0);cout << bitset<8>(v) << endl;
bit::clear(v, 0,1);cout << bitset<8>(v) << endl;
bit::flip(v, 0,1);cout << bitset<8>(v) << endl;
bit::clear(v, 0,1,2,3,4,5,6,7);cout << bitset<8>(v) << endl;
bit::flip(v, 0,7);cout << bitset<8>(v) << endl;}

顺便说一句:事实证明,如果不将优化器参数(例如:-O3)发送到编译器,则不会被使用。随意尝试https://godbolt.org/的代码并查看ASM输出。

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);}

先假设几件事情
num = 55执行按位操作的整数(设置、获取、清除、切换)。
n = 4基于位位置执行按位操作。

如何得到一点?

  1. 要获得num的nth位右移numn次。然后用1执行按位与&
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)

如何设置一个位?

  1. 要设置特定的数字位。左移1n次。然后用num执行按位或|操作。
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)

如何清除一点?

  1. 左移1,n次即1 << n
  2. 对上述结果执行按位补码。使第n位变为未设置,其余位变为设置,即~ (1 << n)
  3. 最后,用上述结果和num进行按位与&运算。上述三步合在一起可以写成num & (~ (1 << n))

清除一点的步骤

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)

如何切换一点?

要切换位,我们使用按位异或^运算符。如果两个操作数的对应位不同,按位异或运算符的计算结果为1,否则计算结果为0。

这意味着要切换位,我们需要使用要切换的位和1执行XOR操作。

num ^= (1 << n);    // Equivalent to; num = num ^ (1 << n);

它是如何工作的?

  • 如果要切换的位为0,则0 ^ 1 => 1
  • 如果要切换的位是1,则1 ^ 1 => 0
       0000 0001 (1 in decimal)<<         4 (left shift 4 times)-----------------0001 0000^ 0011 0111 (55 in decimal)-----------------=> 0010 0111 (final result)

推荐阅读:按位运算符练习

本程序基于@Jeremy的上述解决方案。如果有人想快速播放。

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 :800true

将第n位设置为x(位值)而不使用-1

有时当你不确定-1或类似的结果时,你可能希望设置第n位而不使用-1:

number = (((number | (1 << n)) ^ (1 << n))) | (x << n);

解释:((number | (1 << n)将第n位设置为1(其中|表示按位或),然后使用(...) ^ (1 << n)将第n位设置为0,最后使用(...) | x << n)将第n位设置为0(位值)x

这也适用于golang

以下是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;}