【问题标题】:explain binary_printf function [C lang]解释 binary_printf 函数 [C 语言]
【发布时间】:2022-06-27 17:25:32
【问题描述】:

有人可以解释下面的binary_printf 功能吗? 什么是 maskshift 以及它是如何工作的:

byte = (value & mask) / shift; // Isolate each byte.

我认为它总是给'0'是没用的,还要解释if-else声明byte & 0x80... 一起解释我整个代码?我从乔恩·埃里克森名著黑客:剥削的艺术。用最简单的话解释一下。

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.
    }
}
  • 每一行都有注释——你不明白吗?
  • // Isolate each byte. 没用,它总是给\'0\'。事实并非如此。如果您printf(\"%02X \", byte);,您会看到每个字节的正确值。

标签: c binary bit-manipulation bitwise-operators bit-shift


【解决方案1】:

外部循环运行 4 次,maskshift 的值从 0xff0000000x1000000 开始,然后在循环体的末尾除以 256,因此变为 0xff00000x10000,然后是 @ 987654327@ 和 0x100,最后是 0xff1

内部循环中byte 的值包括最高有效字节的 8 位,然后是之后的字节,依此类推,直到最低有效字节。

内部循环运行 8 次,测试byte 的最高有效字节(if (byte &amp; 0x80) 为真当且仅当最高有效位在byte 中设置),并将byte 中的所有位左移一位在这个循环结束时。

shift 命名为用作除数的值会令人困惑。事实上,编译器是否会将这种除法转换为移位尚不清楚。

可以通过这种方式使用实际的移位运算符简化代码:

void binary_print(unsigned int value)
{
    unsigned int shift = 8 * 3; // 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 >> shift) & 0xff; // 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.
        }
        shift -= 8; // reduce shift amount for the next byte
    }
}

byte 称为 unsigned int 也令人困惑,因为它的值可能不适合一个字节。使用mask0x80 开始并在每次迭代后将其右移一个位置并使用if (byte &amp; mask) 测试每个位会更加一致。

使用这种方法,您实际上可以避免提取字节并使用 32 位 mask 作为单个位,在内部循环中移动:

void binary_print(unsigned int value)
{
    unsigned int mask = 0x8000000000; // Start with a mask for the highest bit.
    unsigned int byte_iterator, bit_iterator;
    for (byte_iterator = 0; byte_iterator < 4; byte_iterator++)
    {
        printf(" ");
        for (bit_iterator = 0; bit_iterator < 8; bit_iterator++)
        {                    // Print the byte's bits.
            if (value & mask) // If the bit in the byte isn't 0,
                printf("1"); // print a 1.
            else
                printf("0"); // Otherwise, print a 0.
            mask >>= 1;      // Skip to the next bit.
        }
    }
}

您可以删除内部循环并使用测试每 8 位输出一个分隔符:

void binary_print(unsigned int value)
{
    unsigned int mask = 0x8000000000;     // Start with a mask for the highest bit.
    unsigned int bit_iterator;
    for (bit_iterator = 0; bit_iterator < 32; bit_iterator++)
    {
        if (mask & 0x80808080)  // output a space every 8 bits
            printf(" ");
        if (value & mask)    // If the bit in value isn't 0,
            printf("1");     // print a 1.
        else
            printf("0");     // Otherwise, print a 0.
        mask >>= 1;          // Skip to the next bit.
    }
}

使用bit_iteratormask 实际上是多余的。这是一个进一步简化的版本:

void binary_print(unsigned int value)
{
    unsigned int mask;       // Use a bit mask starting from the highest bit
    for (mask = 0x8000000000; mask != 0; mask >>= 1)
    {
        if (mask & 0x80808080) // output a space every 8 bits
            printf(" ");
        if (value & mask)    // If the bit in value is set,
            printf("1");     // print a 1.
        else
            printf("0");     // Otherwise, print a 0.
    }
}

使用这种方法,您可以轻松地以不同的方式对位进行分组,例如:if (mask &amp; 0x00808080) 将避免打印初始空间,if (mask &amp; 0x08888888) 将输出 8 组 4 位。

另请注意,所有 3 个printf 调用都可以更改为使用适当字符常量对putchar 的调用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-16
    • 1970-01-01
    • 2018-06-02
    • 2011-04-09
    • 1970-01-01
    • 1970-01-01
    • 2010-09-06
    相关资源
    最近更新 更多