【问题标题】:bit operations in cc中的位操作
【发布时间】:2010-01-13 03:55:54
【问题描述】:

如何反转和旋转十六进制数字并使用位运算符返回 C 中的数字?

例如:

0xabcd -> 0xdcba

0xabcd -> 0xdabc

【问题讨论】:

标签: c bit-manipulation


【解决方案1】:

很难知道从哪里开始提出这个问题。而且我闻到了作业的味道。

几点:

  • 没有“十六进制数”这样的东西。十六进制只是一个符号。你如何反转和旋转十进制数并返回 C 中的数字?例如:

    1776 -> 6771

    1776 -> 6771?

  • 要解决这个问题,您需要对位置表示法有深入的了解,无论是以 10 为底、以 16 为底、以 2 为底,还是你有什么。

  • 所有你需要的都可以通过加、减、乘和除得到。 那些是对数字的操作。模数也很有帮助。

  • 如果您碰巧想要乘以或除以 2 的幂,我推荐您使用 C 左移 << 和右移 >> 运算符。这些对于使用 C 类型 unsignedunsigned long 表示的数字非常有效。

【讨论】:

  • +1 用于解释(以适当粗略的方式)number 与其在特定 base 中的符号之间的区别。
  • 真的吗?当人们认为你不知道定义时,我很生气。仅仅因为你使用了一个语义错误的词并不意味着你不知道它是什么。
  • @Louis:我不认为诺曼是在暗示他不知道它是什么,我认为他是在试图使区别更加清晰。事实上,十进制的“10”是十六进制的“A”,但它们是相同的,因此“切换”十六进制的数字 123 与切换十进制的 123 在数学上是不同的操作,这对大多数人来说并不是很明显人。
  • 哦,是的,我不是在谈论这个特殊情况。我只是发现,如果您使用了错误的术语,很多回复最终都会成为定义。
【解决方案2】:

正如诺曼的回答所指出的那样,十六进制数字是数字。但是,1 个十六进制数字 = 4 位,因此这些操作实际上是有意义的,因为您可能想要对整数值进行操作。

第二个是按位旋转 4 位。请参阅 Best practices for circular shift (rotate) operations in C++ 了解编译器友好型旋转的最佳实践,以防止 C/C++ 未定义行为。

如果您的输入不是 8、16、32 或 64 位,那么您可能需要手动移位 + 掩码,而不是依赖于零移位。


第一个需要更多代码:它颠倒了半字节的顺序。没有机器指令可以做到这一点,也没有简单的方法可以一次对整个数字进行一些按位运算来构建它。

我认为您必须颠倒字节的顺序,然后颠倒每个字节内的半字节顺序(8 位循环 4)。

【讨论】:

    【解决方案3】:

    为了好玩,请遵循适用于任何数字宽度的递归解决方案。

    #include <limits.h>
    unsigned ReverseHex(unsigned x, unsigned DigitWidth) {
      if (DigitWidth <= 1) {
        return x;
      }
      unsigned SideDigitWidth = DigitWidth / 2;
      unsigned SideBitWidth = SideDigitWidth * 4;
      unsigned CenterAndRightDigitWidth = DigitWidth - SideDigitWidth;
      unsigned CenterAndRightBitWidth = CenterAndRightDigitWidth * 4;
      unsigned CenterAndRight = x & ((1u << CenterAndRightBitWidth) - 1);
      unsigned Right = x & ((1u << SideBitWidth) - 1);
      unsigned Center = CenterAndRight - Right;
    
      return ReverseHex(x >> CenterAndRightBitWidth, SideDigitWidth) + Center
          + (ReverseHex(Right, SideDigitWidth) << CenterAndRightBitWidth);
    }
    
    int main(void) {
      printf("%X\n", ReverseHex(0x1234, 4));
      printf("%X\n", ReverseHex(0x12345, 5));
      printf("%X\n", ReverseHex(0x1234567, 7));
      printf("%X\n", ReverseHex(0x12345678, 8));
      return 0;
    }
    

    输出

    4321
    54321
    7654321
    87654321
    

    【讨论】:

      【解决方案4】:

      使用位操作交换数字:

      使用带有适当掩码的原始数字进行按位与运算,以从原始数字中提取一个十六进制数字(4 位)。

      将此提取的位模式移动到它的新位置。

      将重新定位的位模式按位或在一起。

      希望这会有所帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-11-05
        • 2018-04-06
        • 1970-01-01
        • 2017-01-12
        • 2021-12-25
        • 2011-10-14
        • 1970-01-01
        相关资源
        最近更新 更多