C中的按位索引?
我正在尝试实现我已经拥有的数据压缩思想,并且因为我想要在大量的测试数据库中运行它,我曾想过用C语言编写代码(我主要有像Ruby这样的脚本语言的经验。 TCL)。
通过关于C的O’Reilly’牛’书,我意识到我不能简单地索引一个简单的’char’或’int’类型变量的位,因为我想做按位比较和运算符。
我认为这是正确的吗? 使用枚举类型表示一个位(并创建这些数组,并编写函数转换为char和从char转换)是否合理? 如果是这样,是否已在某个标准库中定义了这样的类型和函数? 还有其他(更好的?)方法吗? 是否有人可以指向我的某些示例代码?
谢谢 –
继凯尔所说的之后,你可以使用宏来为你做艰苦的工作。
有可能的。
要设置第n位,请使用OR:
x | =(1 << 5); //设置右起第6位
要清除一点,请使用AND:
x&=〜(1 << 5); //从第6位开始清除
要翻转一下,请使用XOR:
x ^ =(1 << 5); //翻转右下角
要么…
#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
要获得一点使用shift和AND的值:
(x & (1 << 5)) >> 5 // gets the value (0 or 1) of the 5th-from-right
注意:右移5是为了确保该值为0或1.如果你只对0 /而不是0感兴趣,你就可以顺利完成。
看看这个问题的答案。
理论
没有用于访问或设置内置数据类型的第n位的C语法(例如’char’)。 但是,您可以使用逻辑AND操作访问位,并使用逻辑OR运算设置位。
例如,假设您有一个包含1101的变量,并且您想要检查左侧的第二位。 只需使用0100执行逻辑AND:
1101 0100 ---- AND 0100
如果结果不为零,则必须设置第2位; 否则没有设定。
如果要从左侧设置第3位,则使用0010执行逻辑OR:
1101 0010 ---- OR 1111
您可以使用C运算符&&(用于AND)和|| (用于OR)执行这些任务。 您需要自己构建位访问模式(上例中的0100和0010)。 诀窍是要记住最低有效位(LSB)计数1s,下一个LSB计数2s,然后计数4s等。因此,第n个LSB(从0开始)的位访问模式只是2 ^的值ñ。 在C中计算此值的最简单方法是将二进制值0001(在此四位示例中)向左移动所需的位数。 由于此值在无符号整数数量中始终等于1,因此这只是’1 << n'
例
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 );
各个位可以如下索引。
定义像这样的结构:
struct { unsigned bit0 : 1; unsigned bit1 : 1; unsigned bit2 : 1; unsigned bit3 : 1; unsigned reserved : 28; } bitPattern;
现在,如果我想知道名为“value”的var的各个位值,请执行以下操作:
CopyMemory( &input, &value, sizeof(value) );
要查看位2是高还是低:
int state = bitPattern.bit2;
希望这可以帮助。
尝试使用位域。 请注意,编译器的实现可能会有所不同。
http://publications.gbdirect.co.uk/c_book/chapter6/bitfields.html
如果你想索引一点,你可以:
bit = (char & 0xF0) >> 7;
获取char的msb。 您甚至可以省略正确的class次并在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
这有帮助吗?
有一个标准的库容器:std :: vector。 它专门用于图书馆,节省空间。 还有一个boost dynamic_bitset类。
这些将允许您对一组布尔值执行操作,每个底层存储值使用一位。
提升动态bitset文档
有关STL文档,请参阅编译器文档。
当然,您也可以手动处理其他整数类型中的各个位。 如果你这样做,你应该使用无符号类型,这样如果决定对设置了高位的值进行右移,就不会得到未定义的行为。 但是,听起来你想要容器。
对于声称这需要比所需空间多32倍的评论者:boost :: dynamic_bitset和vector专门用于每个条目一位,因此没有空间损失,假设您实际上想要的比特数多于原始类型。 这些类允许您使用高效的底层存储来处理大容器中的各个位。 如果您只想要(比方说)32位,请务必使用int。 如果需要大量的位,可以使用库容器。