【发布时间】:2010-01-13 03:55:54
【问题描述】:
如何反转和旋转十六进制数字并使用位运算符返回 C 中的数字?
例如:
0xabcd -> 0xdcba
0xabcd -> 0xdabc
【问题讨论】:
-
第二个是按位旋转 4 位。请参阅stackoverflow.com/questions/776508/…,了解编译器友好的旋转以防止未定义行为的最佳实践。
标签: c bit-manipulation
如何反转和旋转十六进制数字并使用位运算符返回 C 中的数字?
例如:
0xabcd -> 0xdcba
0xabcd -> 0xdabc
【问题讨论】:
标签: c bit-manipulation
很难知道从哪里开始提出这个问题。而且我闻到了作业的味道。
几点:
没有“十六进制数”这样的东西。十六进制只是一个符号。你如何反转和旋转十进制数并返回 C 中的数字?例如:
1776 -> 6771
1776 -> 6771?
要解决这个问题,您需要对位置表示法有深入的了解,无论是以 10 为底、以 16 为底、以 2 为底,还是你有什么。
所有你需要的都可以通过加、减、乘和除得到。 那些是对数字的操作。模数也很有帮助。
如果您碰巧想要乘以或除以 2 的幂,我推荐您使用 C 左移 << 和右移 >> 运算符。这些对于使用 C 类型 unsigned 或 unsigned long 表示的数字非常有效。
【讨论】:
正如诺曼的回答所指出的那样,十六进制数字是数字。但是,1 个十六进制数字 = 4 位,因此这些操作实际上是有意义的,因为您可能想要对整数值进行操作。
第二个是按位旋转 4 位。请参阅 Best practices for circular shift (rotate) operations in C++ 了解编译器友好型旋转的最佳实践,以防止 C/C++ 未定义行为。
如果您的输入不是 8、16、32 或 64 位,那么您可能需要手动移位 + 掩码,而不是依赖于零移位。
第一个需要更多代码:它颠倒了半字节的顺序。没有机器指令可以做到这一点,也没有简单的方法可以一次对整个数字进行一些按位运算来构建它。
我认为您必须颠倒字节的顺序,然后颠倒每个字节内的半字节顺序(8 位循环 4)。
【讨论】:
为了好玩,请遵循适用于任何数字宽度的递归解决方案。
#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 位)。
将此提取的位模式移动到它的新位置。
将重新定位的位模式按位或在一起。
希望这会有所帮助。
【讨论】: