在C中按位索引?
我正在尝试实现一个已有的数据压缩想法,并且由于我想将其运行在大量测试数据上,因此我曾考虑过用C编写代码(我在Ruby和Tcl。)
浏览关于C的O'Reilly'cow'书,我意识到我不能像我想进行按位比较和运算符那样简单地索引简单的'char'或者'int'类型变量的位。
我的看法正确吗?对我来说,使用枚举类型来表示位是否合理(并组成这些数组并编写用于与char相互转换的函数)?如果是这样,在标准库中定义的这种类型和功能是否已经存在?还有其他(更好的)方法吗?有人可以指出我的地方是否有一些示例代码?
谢谢 -
解决方案
回答
有可能的。
要设置第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感兴趣,则无需进行移位即可。
回答
如果我们想索引一下,可以:
bit = (char & 0xF0) >> 7;
获取一个字符的最高位。我们甚至可以忽略右移并在0上进行测试。
bit = char & 0xF0;
如果该位置1,则结果将> 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
这有帮助吗?
回答
看看这个问题的答案。
回答
要查询具有特定索引的位状态:
int index_state = variable & ( 1 << bit_index );
设置位:
varabile |= 1 << bit_index;
重新启动位:
variable &= ~( 1 << bit_index );
回答
有一个用于位的标准库容器:std :: vector。它在图书馆中专门用于节省空间。还有一个boost dynamic_bitset类。
这些使我们可以对一组布尔值执行操作,基础存储的每个值使用一位。
提升动态位集文档
有关STL文档,请参见编译器文档。
当然,我们也可以手动处理其他整数类型中的各个位。如果这样做,则应使用无符号类型,以便在决定对设置了高位的值进行右移时不会出现未定义的行为。但是,听起来我们想要容器。
对于声称这比必需的空间多32倍的评论者:boost :: dynamic_bitset和vector专门用于每个条目使用一位,因此,假设我们实际上想要的位数超过了位数,则不会有空间损失。基本类型。这些类使我们可以通过有效的基础存储来处理大型容器中的各个位。如果我们只想(说)32位,请使用int。如果需要大量的位,则可以使用库容器。
回答
尝试使用位域。请注意,实现可能因编译器而异。
http://publications.gbdirect.co.uk/c_book/chapter6/bitfields.html
回答
理论
没有C语言语法可以访问或者设置内置数据类型的第n位(例如'char')。但是,我们可以使用逻辑"与"操作访问位,并使用逻辑"或者"操作设置位。
举例来说,假设我们有一个包含1101的变量,并且想要从左开始检查第二位。只需使用0100进行逻辑与:
1101 0100 ---- AND 0100
如果结果不为零,则必须设置第二位;否则,设置为0。否则未设置。
如果要从左开始设置第3位,则对0010执行逻辑或者:
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);
此示例尚未经过测试,但应用于说明总体思路。
回答
按照Kyle所说的,我们可以使用宏为我们完成艰苦的工作。
It is possible. To set the nth bit, use OR: x |= (1 << 5); // sets the 6th-from right To clear a bit, use AND: x &= ~(1 << 5); // clears 6th-from-right To flip a bit, use XOR: x ^= (1 << 5); // flips 6th-from-right
或者...
#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 }
回答
各个位的索引如下。
定义这样的结构:
struct { unsigned bit0 : 1; unsigned bit1 : 1; unsigned bit2 : 1; unsigned bit3 : 1; unsigned reserved : 28; } bitPattern;
现在,如果我想知道名为" value"的变量的各个位值,请执行以下操作:
CopyMemory( &input, &value, sizeof(value) );
要查看第2位是高还是低:
int state = bitPattern.bit2;
希望这可以帮助。