我对按位操作有些熟悉,但是这个功能让我感到头疼。
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
时, value
,value
中的所有位都将被设置为0,除了那些与mask
指定的字节相对应的位,这些位将保留其值。shift
设置为相应的值,通过与shift
的除法,恰好是在掩码中幸存下来的那些位将最终出现在最右边的位(请参阅问题3的答案)。
因此,假设value
是0xDEADBEEF
,mask
具有其初始值0xff000000
,并且shift
具有其初始值256*256*256
。那么value & mask
是0xDE000000
,最终结果是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位。
例如,在这里使用这些操作将值
0xff000000
从0x00ff0000
更改为0x0000ff00
,0x000000ff
,最后更改为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)
中的所有位。表达式value
从i
中选择所需的位,从右起第32位(当i
为31时),从右起第1位(当为0时)结束。关于c - C语言中的按位逻辑,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/14911216/