我正在尝试实现我的数据压缩想法,并且由于我想象针对大量测试数据运行它,所以我曾想过用 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 类。

这些将允许您对一组布尔值执行操作,使用底层存储的每个值一位。

Boost 动态位集文档

有关 STL 文档,请参阅您的编译器文档。

当然,您也可以手动寻址其他整数类型中的各个位。如果这样做,您应该使用无符号类型,以便在决定对设置了高位的值进行右移时不会出现未定义的行为。但是,听起来您想要容器。

对于声称这占用了比必要空间多 32 倍的空间的评论者:boost::dynamic_bitset 和 vector 专门用于每个条目使用一位,因此假设您实际上想要的位数大于原始类型中的位数,则不会有空间损失。这些类允许您通过高效的底层存储来寻址大型容器中的各个位。如果您只想要(比如说)32 位,请务必使用 int。如果您需要大量位,可以使用库容器。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top