题
我正在尝试实现我的数据压缩想法,并且由于我想象针对大量测试数据运行它,所以我曾想过用 C 对其进行编码(我主要有 Ruby 等脚本语言的经验)天哪。)
浏览 O'Reilly 的 Cow 书籍,我意识到我不能简单地对简单的 char 或 int 类型变量的位进行索引,就像我想做的按位比较和运算符一样。
我的这个认识正确吗?我使用枚举类型来表示位(并创建一个数组,并编写与 char 相互转换的函数)是否合理?如果是这样,标准库中是否已经定义了这样的类型和函数?还有其他(更好的?)方法吗?有人可以向我指出一些示例代码吗?
谢谢 -
解决方案
根据凯尔所说,您可以使用宏来为您完成艰苦的工作。
有可能的。
要设置第 n 位,请使用 OR:
x |= (1 << 5);//设置第六次正确
要清除一点,请使用 AND:
x &= ~(1 << 5);//清除第六右右
要翻转一点,请使用 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
要获取位的值,请使用移位和 AND:
(x & (1 << 5)) >> 5 // gets the value (0 or 1) of the 5th-from-right
笔记:右移 5 是为了确保该值为 0 或 1。如果您只对 0/而不是 0 感兴趣,那么无需轮班也可以过得去。
看看以下问题的答案 这个问题.
理论
没有用于访问或设置内置数据类型的第 n 位的 C 语法(例如一个“字符”)。但是,您可以使用逻辑 AND 运算访问位,并使用逻辑 OR 运算设置位。
举个例子,假设您有一个保存 1101 的变量,并且您想要检查左侧的第二位。只需与 0100 执行逻辑 AND:
1101
0100
---- AND
0100
如果结果非零,则必须设置第 2 位;否则未设置。
如果要设置左起第3位,则与0010执行逻辑或:
1101
0010
---- OR
1111
您可以使用C运算符&&(用于和)和|| (对于OR)执行这些任务。您需要自己构建位访问模式(上面示例中的 0100 和 0010)。诀窍是记住最低有效位 (LSB) 计数为 1,下一个 LSB 计数为 2,然后是 4,依此类推。因此,第 n 个 LSB(从 0 开始)的位访问模式就是 2^n 的值。在 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;
获取字符的最高有效位。您甚至可以省略右移并在 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
ETC...
这给你:
bit = char & BIT_1;
您可以在上面的代码中使用这些定义来成功索引宏或函数中的位。
设置一点:
char |= BIT_2;
清除一下:
char &= ~BIT_3
切换一下
char ^= BIT_4
这有帮助吗?
有一个位的标准库容器:std::向量。它专门用于图书馆,以节省空间。还有一个 boostdynamic_bitset 类。
这些将允许您对一组布尔值执行操作,使用底层存储的每个值一位。
有关 STL 文档,请参阅您的编译器文档。
当然,您也可以手动寻址其他整数类型中的各个位。如果这样做,您应该使用无符号类型,以便在决定对设置了高位的值进行右移时不会出现未定义的行为。但是,听起来您想要容器。
对于声称这占用了比必要空间多 32 倍的空间的评论者:boost::dynamic_bitset 和 vector 专门用于每个条目使用一位,因此假设您实际上想要的位数大于原始类型中的位数,则不会有空间损失。这些类允许您通过高效的底层存储来寻址大型容器中的各个位。如果您只想要(比如说)32 位,请务必使用 int。如果您需要大量位,可以使用库容器。