我对按位操作有些熟悉,但是这个功能让我感到头疼。

void binary_print(unsigned int value) {
  unsigned int mask = 0xff000000;   // Start with a mask for the highest byte.
  unsigned int shift = 256*256*256; // Start with a shift for the highest byte.
  unsigned int byte, byte_iterator, bit_iterator;

  for (byte_iterator=0; byte_iterator < 4; byte_iterator++) {
    byte = (value & mask) / shift; // Isolate each byte.
    printf(" ");

    for (bit_iterator=0; bit_iterator < 8; bit_iterator++) {
      // Print the byte's bits.
      if (byte & 0x80) // If the highest bit in the byte isn't 0,
        printf("1");   // print a 1.
      else
        printf("0");   // Otherwise, print a 0.

      byte *= 2;       // Move all the bits to the left by 1.
    }
    mask /= 256;       // Move the bits in mask right by 8.
    shift /= 256;      // Move the bits in shift right by 8.
  }
}


此函数接收open()函数的位标志,并在display_flags函数的帮助下(添加适当的标签)产生以下输出:

O_RDONLY : 0 : 00000000 00000000 00000000 00000000
O_WRONLY : 1 : 00000000 00000000 00000000 00000001
O_RDWR : 2 : 00000000 00000000 00000000 00000010
O_APPEND : 1024 : 00000000 00000000 00000100 00000000
O_TRUNC : 512 : 00000000 00000000 00000010 00000000
O_CREAT : 64 : 00000000 00000000 00000000 01000000
O_WRONLY|O_APPEND|O_CREAT : 1089 : 00000000 00000000 00000100 01000001


我理解输出没有问题,但是我不理解实际过程:


byte = (value & mask) / shift如何隔离单个位?
为什么if(byte & 0x80)表示“如果字节中的最高位不为0?”
这些行:byte *= 2;mask /= 256;shift /= 256;如何移动位,为什么该操作有意义?

最佳答案

1. byte = (value & mask) / shift如何隔离各个位?

mask是始终将8个连续位设置为1,其余设置为0的位模式(它以0xff000000开头,然后是0x00ff0000,依此类推。因此,当按位取mask时, valuevalue中的所有位都将被设置为0,除了那些与mask指定的字节相对应的位,这些位将保留其值。

shift设置为相应的值,通过与shift的除法,恰好是在掩码中幸存下来的那些位将最终出现在最右边的位(请参阅问题3的答案)。

因此,假设value0xDEADBEEFmask具有其初始值0xff000000,并且shift具有其初始值256*256*256。那么value & mask0xDE000000,最终结果是0x000000DE

用二进制的例子是

value       = 11011110101011011011111011101111
mask        = 11111111000000000000000000000000
byte & mask = 11011110000000000000000000000000
result      = 00000000000000000000000001101111


2.为什么if(byte & 0x80)表示“如果字节中的最高位不为0?”

在这里,代码作者认为byte是8位变量。尽管从技术上讲更大,但此处不再使用高位。因此,当作者指的是“最高位”时,请想到右边的第8位(如果byte实际上只有一个字节,则该位为最高位)。

现在注意0x80是二进制的10000000。因此,当您使用byte & 0x80时,除“最高”(从右数第8位)一位以外,所有来自byte的位都将设为0。因此,如果byte & 0x80的最高位为零,则byte为零;如果byte的“最高”位为1,则byte *= 2;为零。

3.这些行:mask /= 256;shift /= 256;1001如何移动位,为什么该操作很重要?

与2的乘积等效于左移1位。例如,考虑值9,该值在二进制中为10010。 2的乘积得到18,它是二进制的mask

与2除法类似,这是向右移1。256的除法等效于8除以2,所以256的除法等效于右移8位。
例如,在这里使用这些操作将值0xff0000000x00ff0000更改为0x0000ff000x000000ff,最后更改为value

全功能说明

有了这些知识,我们可以看到完整功能的作用。在外部循环中,它循环遍历byte中的4个字节,从最左边的一个字节开始,到最右边的一个字节结束。它通过屏蔽当前字节并将其存储在byte中来实现。

然后,内部循环遍历存储在value中的8位。它总是从右边开始看第8位,并相应地打印1或0。然后将这些位向左移动,以便在第二次迭代中,从右数第7位的位现在是从右数第8位的位,将被打印,然后再打印一个,依此类推,直到所有8位都从右到右打印为止。 -左顺序。

编写此函数的另一种方法是

for (int i = 31; i >= 0; i--) {
  if (value & (1 << i))
    printf("1");
  else
    printf("0");

  if (i % 8 == 0)
    printf(" ");
}


这将简单地以从左到右的顺序遍历value (1 << i)中的所有位。表达式valuei中选择所需的位,从右起第32位(当i为31时),从右起第1位(当为0时)结束。

关于c - C语言中的按位逻辑,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/14911216/

10-11 22:35
查看更多