您如何设置,清除和切换?
您如何设置,清除和切换?
Answers:
使用按位或运算符(|
)进行设置。
number |= 1UL << n;
这将设置的n
第一位number
。n
如果要设置1
st位,则应为零;如果n-1
要设置n
th位,则应为upto 。
使用1ULL
如果number
超过更宽unsigned long
; 1UL << n
直到评估1UL << n
了未定义行为的偏移量大于宽度之后,才会提升long
。其他所有示例也是如此。
使用按位AND运算符(&
)清除一位。
number &= ~(1UL << n);
这将清除的n
第一个位number
。您必须使用按位NOT运算符(~
)反转位字符串,然后将其取反。
XOR运算符(^
)可用于切换一位。
number ^= 1UL << n;
这将切换n
的个位number
。
您没有要求这样做,但我也可以添加它。
要检查一点,请将数字n右移,然后按位与它相乘:
bit = (number >> n) & 1U;
这会将n
第th位的值number
放入变量bit
。
在2的补码C ++实现中,可以通过以下方式将n
th位设置为1
或0
:
number ^= (-x ^ number) & (1UL << n);
位n
,如果将被设置x
为1
,如果清除x
是0
。如果x
还有其他价值,您将得到垃圾。 x = !!x
会将其布尔值设为0或1。
为了使它独立于2的补码取反行为(-1
与1的补码或正负号/幅值C ++实现不同,所有位都已置1),请使用无符号取反。
number ^= (-(unsigned long)x ^ number) & (1UL << n);
要么
unsigned long newbit = !!x; // Also booleanize to force 0 or 1
number ^= (-newbit ^ number) & (1UL << n);
使用无符号类型进行可移植位操作通常是一个好主意。
要么
number = (number & ~(1UL << n)) | (x << n);
(number & ~(1UL << n))
将清除n
th位并将th位(x << n)
设置n
为x
。
通常也不要复制/粘贴代码,这也是一个好主意,因此许多人使用预处理器宏(例如社区Wiki进一步回答)或某种封装。
bit = (number >> x) & 1
1
是一个带int
符号的文字。因此,此处的所有操作都对带符号的数字进行操作,而该数字并未由标准明确定义。标准不保证二进制补码或算术移位,因此最好使用1U
。
number = number & ~(1 << n) | (x << n);
将第n位更改为x。
使用标准C ++库: std::bitset<N>
。
或Boost版本:boost::dynamic_bitset
。
无需自己动手:
#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.out
00010
与标准库编译时大小的位组相比,Boost版本允许运行时大小的位组。
另一种选择是使用位字段:
struct bits {
unsigned int a:1;
unsigned int b:1;
unsigned int c:1;
};
struct bits mybits;
定义一个3位字段(实际上是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
这仅适用于固定大小的位字段。否则,您必须诉诸以前的帖子中介绍的位旋转技术。
我使用在头文件中定义的宏来处理位设置和清除:
/* 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)) == (y)) // warning: evaluates y twice
#define BITMASK_CHECK_ANY(x,y) ((x) & (y))
BITMASK_CHECK(x,y) ((x) & (y))
((x) & (y)) == (y)
否则必须返回,否则它会在多位掩码(例如5
vs 。3
)/ *向所有掘墓者返回错误的结果:)* /
1
(uintmax_t)1
如果有人尝试在long
更大或更大型的类型上使用这些宏,则应为或相似
BITMASK_CHECK_ALL(x,y)
可以实现为!~((~(y))|(x))
!(~(x) & (y))
它有时是值得使用enum
来命名的位:
enum ThingFlags = {
ThingMask = 0x0000,
ThingFlag0 = 1 << 0,
ThingFlag1 = 1 << 1,
ThingError = 1 << 8,
}
然后使用这些名称。即写
thingstate |= ThingFlag1;
thingstate &= ~ThingFlag0;
if (thing & ThingError) {...}
进行设置,清除和测试。这样,您就可以在其余代码中隐藏幻数。
除此之外,我赞同杰里米的解决方案。
clearbits()
函数代替&= ~
。您为什么为此使用枚举?我以为是用隐藏的任意值创建一堆唯一变量,但是您要为每个变量分配一个确定值。那么与仅将它们定义为变量相比有什么好处?
enum
在c编程中,将s用于相关常量集可以追溯很长时间。我怀疑对于现代编译器而言,唯一的优势const short
是将它们明确地组合在一起。当您希望它们用于位掩码之外的其他东西时,您会得到自动编号。当然,在c ++中,它们还形成不同的类型,这为您提供了一些额外的静态错误检查。
enum ThingFlags
值是ThingError|ThingFlag1
多少?
int
。由于隐式整数提升或对有符号类型进行按位运算,这可能导致各种形式的细微错误。thingstate = ThingFlag1 >> 1
例如将调用实现定义的行为。thingstate = (ThingFlag1 >> x) << y
可以调用未定义的行为。等等。为了安全起见,请始终强制转换为无符号类型。
enum My16Bits: unsigned short { ... };
/*
** 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字段,在指定位置带有1。唯一棘手的部分是在BitClr()宏中,我们需要在1的字段中设置单个0位。这可以通过使用与代字号(〜)运算符相同的表达式的1的补码来实现。
一旦创建了掩码,就可以使用按位运算符(&)或(|)和xor(^)运算符,按照您的建议将其应用于自变量。由于掩码的类型为long,因此宏在char,short,int或long上也可以使用。
最重要的是,这是对整个问题类别的通用解决方案。当然,每次您需要时,都可以使用显式掩码值重写这些宏的等效项,但是为什么这样做呢?请记住,宏替换发生在预处理器中,因此生成的代码将反映以下事实:编译器将值视为常量。也就是说,使用通用宏与每次需要“重新发明轮子”一样有效。做位操作。
不服气?这是一些测试代码-我使用Watcom C进行了全面优化,而没有使用_cdecl,因此所产生的反汇编应尽可能干净:
---- [TEST.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;
}
---- [TEST.OUT(已分解)] -------------------------------------- ---------
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] ------------------------------------------- ----------------------
arg
为,则将失败long long
。 1L
必须是尽可能宽的类型,因此(uintmax_t)1
。(您可能会逃脱1ull
)
对于初学者,我想用一个例子来解释一下:
例:
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)
这是我最喜欢的位算术宏,它适用于从0 unsigned char
到0的任何类型的无符号整数数组size_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, &)) ...
等等
BITOP(array, bit++, |=);
在循环中使用将很可能不会执行呼叫者想要的操作。
BITCELL(a,b) |= BITMASK(a,b);
(两者均a
作为确定大小的参数,但后者从不求值,a
因为它仅出现在中sizeof
。
(size_t)
投似乎只存在,以确保一些无符号数有%
。可以(unsigned)
在那里。
(size_t)(b)/(8*sizeof *(a))
不必要可以缩小b
师前。只有非常大的位数组才有问题。仍然是一个有趣的宏。
因为这被标记为“嵌入式”,所以我假设您正在使用微控制器。以上所有建议都是有效且可行的(读取,修改,写入,联合,结构等)。
但是,在基于示波器的调试中,我惊讶地发现与直接将值写入微控制器的PORTnSET / PORTnCLEAR寄存器相比,这些方法在CPU周期上具有相当大的开销,这在存在紧密循环/高电平的情况下确实有所不同频率ISR的切换引脚。
对于那些不熟悉的人:在我的示例中,微控制器具有反映输出引脚的通用引脚状态寄存器PORTn,因此执行PORTn | = BIT_TO_SET会导致对该寄存器进行读-修改-写操作。但是,PORTnSET / PORTnCLEAR寄存器为1表示“请将该位设为1”(SET)或“请将该位设为0”(CLEAR),为0则表示“请单独保留该引脚”。所以,你最终有两个端口地址取决于是否你设置或清除该位(并不总是很方便),但很多更快的反应和更小的汇编代码。
volatile
,因此编译器无法对涉及此类寄存器的代码执行任何优化。因此,优良作法是反汇编此类代码,并在汇编程序级别查看其结果。
位域方法在嵌入式领域具有其他优势。您可以定义直接映射到特定硬件寄存器中位的结构。
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,但这可能取决于实现。另外,请验证编译器如何处理跨越字节边界的字段。
然后,您可以像以前一样读取,写入,测试各个值。
#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测试了它。可以制作相似的宏来设置和清除位。与许多其他解决方案相比,此解决方案的主要区别在于,它几乎可以在任何类型的变量中的任何位置使用。
该程序将任何数据位从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);
}
}
}
如果您要花很多时间在摆弄,您可能需要使用遮罩,这样可以使整个过程更快。以下功能非常快速且仍然很灵活(它们允许在任何大小的位图中旋转位)。
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);
您需要确保位数在您传递的位图范围内。请注意,对于字节,字,双字,qword等在内存中正确相互映射的小端处理器,主要原因是小端处理器比大端处理器“更好”,是啊,我觉得火焰之战正在到来上...)。
扩大bitset
答案:
#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;
}
如果要在Linux内核中使用C编程执行所有这些操作,则建议使用Linux内核的标准API。
参见https://www.kernel.org/doc/htmldocs/kernel-api/ch02s03.html
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
注意:此处整个操作只需一步即可完成。因此,即使在SMP计算机上,也保证了所有这些原子性,并且对于保持处理器之间的一致性很有用。
Visual C 2010,也许还有许多其他编译器,都直接支持内置的布尔操作。一个位具有两个可能的值,就像布尔值一样,因此我们可以改用布尔值-即使它们占用的空间大于单个位。以这种形式记忆。这可以正常工作,即使sizeof()
操作员也可以正常工作。
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);
}
因此,对于您的问题,IsGph[i] =1
或IsGph[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个值。
我曾经使用这种方法来查找重复的贷方记录,其中贷方编号是ISAM密钥,使用6位数的贷方编号作为位数组的索引。经过8个月的迅速开发,证明了我们从中获取数据的大型机系统实际上发生了故障。位数组的简单性使其对正确性的置信度很高-例如,与搜索方法相比。
bool
。甚至4个字节用于C89的设置使用int
来实现bool
这是我使用的一些宏:
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)
使用变量
int value, pos;
价值-数据
位-我们想要设置,清除或切换的位的位置。
设置一点:
value = value | 1 << pos;
清除一点:
value = value & ~(1 << pos);
切换一下:
value = value ^ 1 << pos;
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);
}
check_nth_bit
可以为bool
。
首先假设一些事情
num = 55
整数执行位运算(设置,获取,清除,切换)。
n = 4
基于0的位位置以执行按位运算。
nth
NUM右移位num
,n
倍。然后&
与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)
n
次。然后使用进行按位或|
运算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)
n
次,即1 << n
。~ (1 << n)
。&
对上述结果和进行按位与运算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)
为了切换一点,我们使用按位XOR ^
运算符。如果两个操作数的对应位不同,则按位XOR运算符的计算结果为1,否则为0。
这意味着要切换一个位,我们需要对要切换的位和1执行XOR操作。
num ^= (1 << n); // Equivalent to; num = num ^ (1 << n);
怎么运行的?
0 ^ 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)
推荐阅读- 按位操作员练习
如何设置,清除和切换单个位?
在尝试形成遮罩时要解决常见的编码陷阱:
1
并不总是足够宽
如果number
类型大于,会发生什么问题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
也可以花哨地(uintmax_t)1
使编译器进行优化。
number |= (1ull << x);
number |= ((uintmax_t)1 << x);
或强制转换-导致编码/审查/维护问题,使强制转换正确并保持最新状态。
number |= (type_of_number)1 << x;
或1
通过强制进行宽度最小的数学运算来轻轻地促进运算number
。
number |= (number*0 + 1) << x;
与大多数位操作,最好与工作无符号的类型,而不是签署者
number |= (type_of_number)1 << x;
也不number |= (number*0 + 1) << x;
适合设置一个符号类型的符号位......作为事实上,也不是number |= (1ull << x);
。有没有一种便携式的位置定位方法?
一个C ++ 11模板版本(放入标头):
namespace bit {
template <typename T1, typename T2> inline void set (T1 &variable, T2 bit) {variable |= ((T1)1 << bit);}
template <typename T1, typename T2> inline void clear(T1 &variable, T2 bit) {variable &= ~((T1)1 << bit);}
template <typename T1, typename T2> inline void flip (T1 &variable, T2 bit) {variable ^= ((T1)1 << bit);}
template <typename T1, typename T2> inline bool test (T1 &variable, T2 bit) {return variable & ((T1)1 << bit);}
}
namespace bitmask {
template <typename T1, typename T2> inline void set (T1 &variable, T2 bits) {variable |= bits;}
template <typename T1, typename T2> inline void clear(T1 &variable, T2 bits) {variable &= ~bits;}
template <typename T1, typename T2> inline void flip (T1 &variable, T2 bits) {variable ^= bits;}
template <typename T1, typename T2> inline bool test_all(T1 &variable, T2 bits) {return ((variable & bits) == bits);}
template <typename T1, typename T2> inline bool test_any(T1 &variable, T2 bits) {return variable & bits;}
}
;
定义函数?)
(variable & bits == bits)
?
((variable & bits) == bits)
std::bitset
在C ++ 11
该程序基于@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 :
8
0
0
true
尝试使用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;
else
bitfield &= ~0 ^ (1 << n);
}
char get_n_bit(int n)
{
return (bitfield & (1 << n)) ? 1 : 0;
}
value << n
可能会导致不确定的行为