在查看O'Reilly关于C语言的书籍时,我意识到我不能像我想要的那样索引简单的“char”或“int”类型变量的位来进行位比较和操作。
我的感知是正确的吗?我是否可以使用枚举类型表示一位(并创建一个这些的数组,并编写将其转换为char的函数和从char转换回该类型的函数)?如果可以,这种类型和函数是否已经在标准库中定义了?还有其他更好的方法吗?是否有某个示例代码可以指导我?
谢谢。
继Kyle所说的之后,您可以使用宏来为您完成艰苦的工作。
这是可能的。
要设置第n位,请使用OR:
x |= (1 << 5); // 设置从右数第6位
要清除一位,请使用AND:
x &= ~(1 << 5); // 清除从右数第6位
要翻转一位,请使用XOR:
x ^= (1 << 5); // 翻转从右数第6位
或者...
#define GetBit(var, bit) ((var & (1 << bit)) != 0) // Returns true / false if bit is set
#define SetBit(var, bit) (var |= (1 << bit))
#define FlipBit(var, bit) (var ^= (1 << bit))
然后您可以像这样在代码中使用它:
int myVar = 0;
SetBit(myVar, 5);
if (GetBit(myVar, 5))
{
// Do something
}
这是可能的。
要设置第n位,使用OR:
x |= (1 << 5); // sets the 5th-from right
如果要清除某个位,可以使用 AND:
x &= ~(1 << 5); // clears 5th-from-right
要翻转一个比特,请使用异或(XOR):
x ^= (1 << 5); // flips 5th-from-right
要获取一个位的值,使用移位和按位与操作:
(x & (1 << 5)) >> 5 // gets the value (0 or 1) of the 5th-from-right
注:右移 5 位是为了确保该值为 0 或 1。如果您只关心 0/不为 0,则可以在不进行移位的情况下完成。
理论
在C语言中,没有直接访问或设置内置数据类型(例如 'char')的第n位的语法。但是,您可以使用逻辑 AND 操作访问位,并使用逻辑 OR 操作设置位。
举个例子,假设您有一个变量保存了1101,您想检查左边第二位。只需使用0100进行逻辑 AND 操作:
1101
0100
---- AND
0100
1101
0010
---- OR
1111
unsigned char myVal = 0x65; /* in hex; this is 01100101 in binary. */
/* Q: is the 3-rd least significant bit set (again, the LSB is the 0th bit)? */
unsigned char pattern = 1;
pattern <<= 3; /* Shift pattern left by three places.*/
if(myVal && (char)(1<<3)) {printf("Yes!\n");} /* Perform the test. */
/* Set the most significant bit. */
myVal |= (char)(1<<7);
这个例子没有经过测试,但应该可以用来说明一般的思路。
查询特定索引位的状态:
int index_state = variable & ( 1 << bit_index );
设置位:
varabile |= 1 << bit_index;
重新启动位:
variable &= ~( 1 << bit_index );
如果您想索引一位,您可以:
bit = (char & 0xF0) >> 7;
获取 char 的最高有效位(MSB)。您甚至可以省略右移并对 0 进行测试。
bit = char & 0xF0;
如果位被设置,结果将会大于0;
显然,你需要改变掩码以获取不同的位(注:如果不清楚,0xF是位掩码)。可以定义许多掩码,例如:
#define BIT_0 0x1 // or 1 << 0
#define BIT_1 0x2 // or 1 << 1
#define BIT_2 0x4 // or 1 << 2
#define BIT_3 0x8 // or 1 << 3
这将给你:
bit = char & BIT_1;
您可以在上述代码中使用这些定义来成功地在宏或函数中索引位。
设置位:
char |= BIT_2;
澄清一下:
char &= ~BIT_3
切换一个位
char ^= BIT_4
这有帮助吗?
个别位可以按以下方式进行索引。
定义一个这样的结构体:
struct
{
unsigned bit0 : 1;
unsigned bit1 : 1;
unsigned bit2 : 1;
unsigned bit3 : 1;
unsigned reserved : 28;
} bitPattern;
CopyMemory( &input, &value, sizeof(value) );
判断第二位是高电平还是低电平:
int state = bitPattern.bit2;
有一个标准库容器专门用于位操作:std::vector。在库中进行了特殊优化以提高空间效率。此外,还有一个 Boost dynamic_bitset 类。
这些容器可以让您使用基础存储的每个值的一位来执行布尔值集上的操作。
Boost dynamic bitset documentation
有关 STL 文档,请参阅编译器文档。
当然,您也可以手动访问其他整数类型中的单个位。如果这样做,应使用无符号类型,以便在对带高位设置的值进行右移时不会出现未定义行为。但是,根据您的描述,似乎您需要这些容器。
对于声称这比必要的多占用了32倍空间的评论者:boost::dynamic_bitset和vector专门使用每个条目一个位,因此不存在空间惩罚,假设您实际上需要超过原始类型中的位数。这些类允许您在具有高效底层存储的大容器中寻址单个位。如果您只需要(比如)32位,请使用int。如果您需要大量位数,则可以使用库容器。尝试使用位域(bitfields)。请注意,实现方式可能因编译器而异。
http://publications.gbdirect.co.uk/c_book/chapter6/bitfields.html