简体   繁体   English

遍历 C 中的位

[英]Iterate through bits in C

I have a big char *str where the first 8 chars (which equals 64 bits if I'm not wrong), represents a bitmap.我有一个很大的 char *str ,其中前 8 个字符(如果我没记错的话等于 64 位)代表一个位图。 Is there any way to iterate through these 8 chars and see which bits are 0?有没有办法遍历这 8 个字符并查看哪些位是 0? I'm having alot of trouble understanding the concept of bits, as you can't "see" them in the code, so I can't think of any way to do this.我在理解位的概念时遇到了很多麻烦,因为您无法在代码中“看到”它们,所以我想不出任何方法来做到这一点。

Imagine you have only one byte, a single char my_char .想象一下,你只有一个字节,一个 char my_char You can test for individual bits using bitwise operators and bit shifts.您可以使用按位运算符和位移位测试单个位。

unsigned char my_char = 0xAA;
int what_bit_i_am_testing = 0;

while (what_bit_i_am_testing < 8) {
  if (my_char & 0x01) {
     printf("bit %d is 1\n", what_bit_i_am_testing);
  }
  else {
     printf("bit %d is 0\n", what_bit_i_am_testing);
  }

  what_bit_i_am_testing++;
  my_char = my_char >> 1;
}

The part that must be new to you, is the >> operator.对您来说一定很陌生的部分是>>运算符。 This operator will "insert a zero on the left and push every bit to the right, and the rightmost will be thrown away".此运算符将“在左侧插入一个零并将每一位推到右侧,最右侧的将被丢弃”。

That was not a very technical description for a right bit shift of 1.对于右移 1 来说,这不是一个非常技术性的描述。

Here is a way to iterate over each of the set bits of an unsigned integer (use unsigned rather than signed integers for well-defined behaviour; unsigned of any width should be fine), one bit at a time.这是一种迭代无符号整数的每个设置位的方法(使用无符号而不是有符号整数来实现明确定义的行为;任何宽度的无符号都应该没问题),一次一位。

Define the following macros:定义以下宏:

#define LSBIT(X)                    ((X) & (-(X)))
#define CLEARLSBIT(X)               ((X) & ((X) - 1))

Then you can use the following idiom to iterate over the set bits, LSbit first:然后您可以使用以下习语来迭代设置位,首先是 LSbit:

unsigned temp_bits;
unsigned one_bit;

temp_bits = some_value;
for ( ; temp_bits; temp_bits = CLEARLSBIT(temp_bits) ) {
    one_bit = LSBIT(temp_bits);
    /* Do something with one_bit */
}

I'm not sure whether this suits your needs.我不确定这是否适合您的需求。 You said you want to check for 0 bits, rather than 1 bits — maybe you could bitwise-invert the initial value.你说你想检查0位,而不是1位——也许你可以按位反转初始值。 Also for multi-byte values, you could put it in another for loop to process one byte at a time.同样对于多字节值,您可以将它放在另一个for循环中以一次处理一个字节。

In the C language, chars are 8-bit wide bytes, and in general in computer science, data is organized around bytes as the fundamental unit.在 C 语言中,字符是 8 位宽的字节,一般在计算机科学中,数据是以字节为基本单位进行组织的。

In some cases, such as your problem, data is stored as boolean values in individual bits, so we need a way to determine whether a particular bit in a particular byte is on or off.在某些情况下,例如您的问题,数据存储为单个位中的布尔值,因此我们需要一种方法来确定特定字节中的特定位是打开还是关闭。 There is already an SO solution for this explaining how to do bit manipulations in C .已经有一个 SO 解决方案来解释如何在 C 中进行位操作

To check a bit, the usual method is to AND it with the bit you want to check:要检查一点,通常的方法是将它与要检查的位进行 AND 运算:

int isBitSet = bitmap & (1 << bit_position);

If the variable isBitSet is 0 after this operation, then the bit is not set.如果此操作后变量 isBitSet 为 0,则不设置该位。 Any other value indicates that the bit is on.任何其他值都表示该位已打开。

For one char b you can simply iterate like this :对于一个字符b您可以简单地像这样迭代:

for (int i=0; i<8; i++) {
  printf("This is the %d-th bit : %d\n",i,(b>>i)&1);
}

You can then iterate through the chars as needed.然后,您可以根据需要遍历字符。

What you should understand is that you cannot manipulate directly the bits, you can just use some arithmetic properties of number in base 2 to compute numbers that in some way represents some bits you want to know.您应该理解的是,您不能直接操作这些位,您可以仅使用以 2 为底的数字的一些算术属性来计算以某种方式表示您想知道的某些位的数字。

How does it work for example ?例如它是如何工作的? In a char there is 8 bits.在一个字符中有 8 位。 A char can be see as a number written with 8 bits in base 2. If the number in b is b7b6b5b4b3b2b1b0 (each being a digit) then b>>i is b shifted to the right by i positions (in the left 0's are pushed).一个字符可以看作是一个以 2 为底的 8 位数字。如果 b 中的数字是 b7b6b5b4b3b2b1b0(每个都是一个数字),那么 b>>i 是 b 向右移动 i 个位置(在左边的 0 被推入)。 So, 10110111 >> 2 is 00101101, then the operation &1 isolate the last bit (bitwise and operator).因此,10110111 >> 2 是 00101101,然后操作 &1 隔离最后一位(按位和运算符)。

It's true for little-endian memory architecture:小端内存架构也是如此:

const int cBitmapSize = 8;
const int cBitsCount = cBitmapSize * 8;
const unsigned char cBitmap[cBitmapSize] = /* some data */;

for(int n = 0; n < cBitsCount; n++)
{
  unsigned char Mask = 1 << (n % 8);
  if(cBitmap[n / 8] & Mask)
  {
    // if n'th bit is 1...
  }
}

If you want to iterate through all char.如果要遍历所有字符。

char *str = "MNO"; // M=01001101, N=01001110, O=01001111
int bit = 0;

for (int x = strlen(str)-1; x > -1; x--){ // Start from O, N, M
    
    printf("Char %c \n", str[x]);
 
    for(int y=0; y<8; y++){ // Iterate though every bit
    // Shift bit the the right with y step and mask last position
        if( str[x]>>y & 0b00000001 ){ 
            printf("bit %d = 1\n", bit);
        }else{
            printf("bit %d = 0\n", bit);
        }
        bit++;
    }
    
}

output输出

Char O
bit 0 = 1
bit 1 = 1
bit 2 = 1
bit 3 = 1
bit 4 = 0
bit 5 = 0
bit 6 = 1
bit 7 = 0
Char N 
bit 8 = 0
bit 9 = 1
bit 10 = 1
...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM