8

我正在尝试颠倒 C 中的位顺序(作业问题,主题:按位运算符)。我找到了这个解决方案,但我对使用的十六进制值有点困惑——0x01 和 0x80。

  unsigned char reverse(unsigned char c) {
     int shift;
     unsigned char result = 0;

     for (shift = 0; shift < CHAR_BITS; shift++) {
        if (c & (0x01 << shift))
            result |= (0x80 >> shift);
     }
     return result;
  }

我正在编写的这本书没有讨论过这些价值观,所以我不确定如何理解它们。有人可以阐明这个解决方案吗?谢谢!

4

4 回答 4

8

0x01 是设置的最低有效位,因此十进制值为 1。

0x80 是 8 位字节集的最高有效位。如果它存储在有符号字符中(在使用 2 的补码表示法的机器上 - 正如您可能遇到的大多数机器一样),它是最负的值(十进制 -128);在无符号字符中,它是十进制 +128。

另一种成为第二天性的模式是 0xFF 设置了所有位;这对于有符号字符是十进制 -1,对于无符号字符是 255。而且,当然,没有设置位的 0x00 或零。

循环在第一个循环中所做的是检查是否设置了 LSB(最低有效位),如果是,则在结果中设置 MSB(最高有效位)。在下一个周期,它检查 LSB 的下一个并将下一个设置为 MSB,等等。

| MSB |     |     |     |     |     |     | LSB |
|  1  |  0  |  1  |  1  |  0  |  0  |  1  |  1  |   Input
|  1  |  1  |  0  |  0  |  1  |  1  |  0  |  1  |   Output
|  1  |  0  |  0  |  0  |  0  |  0  |  0  |  0  |   0x80
|  0  |  0  |  0  |  0  |  0  |  0  |  0  |  1  |   0x01
|  0  |  1  |  0  |  0  |  0  |  0  |  0  |  0  |   (0x80 >> 1)
|  0  |  0  |  0  |  0  |  0  |  0  |  1  |  0  |   (0x01 << 1)
于 2010-04-17T23:35:37.047 回答
5

每个十六进制数字代表 4 位,所以

  • 0x01 只是写 1 的很长一段路。
  • 0x80 是二进制 [1000][0000] 或 128 的简写方式。

解决方案是使用按位运算符来测试和设置值。

表达方式:

if (a & b) { ... }

如果在“a”和“b”中相同的位为 1,则执行“...”。

表达方式

c |= b

如果在“b”中为 1,则将“c”中的位设置为 1。

循环将测试和设置位向下移动。

祝你好运!

于 2010-04-17T23:39:19.757 回答
1

0x010x80特意以十六进制表示法来强调它们作为该类型的最低有效位和最高有效位的重要性unsigned char

然而作者犯了几个错误:

  • CHAR_BITS拼写错误:应该是CHAR_BIT.
  • 使用CHAR_BIT几乎通用的值而不是硬编码8是对完全可移植性的一项有价值的努力,但这种努力因使用0x80仅在CHAR_BIT == 8.
  • 还有另一个微妙的可移植性问题:在因为有类型的平台上0x01 << shift会有未定义的行为(而不是,反直觉不是吗?)。shift = CHAR_BIT-1sizeof(unsigned char) == sizeof(int)0x01intunsigned int

这是适用于所有兼容平台的更正版本:

#include <limits.h>

unsigned char reverse(unsigned char c) {
    int shift;
    unsigned char result = 0;

    for (shift = 0; shift < CHAR_BIT; shift++) {
        result <<= 1;
        result |= c & 1;
        c >>= 1;
    }
    return result;
}
于 2019-05-04T17:37:08.140 回答
0

0x01表示 1——一个位中的一个——并且0x80表示 128——一个 16 位中的 8。这些数字分别指的是八位数字中的最低位和最高位。移动它们为字节中的各个位提供掩码。

编辑:在十六进制数中,数字是十六的幂,而不是十的幂。所以从右数第一位是个位(0x1 = 1),第二位是十六位(0x10 = 16),第三位是二百五十六位(0x100 = 256),和很快。

于 2010-04-17T23:36:44.427 回答