首页 > 解决方案 > 带符号字符(C)的位旋转?

问题描述

我正在尝试旋转一个带符号的 char ( *c),它在二进制中是100110104 ( numRotate) 个位置。转变后的期望结果是10101001。我目前拥有的代码是:

void right(char *c, int numRotate) {
    *c = (*c >> numRotate) | (*c << (8 - numRotate));
}

根据我所学到的,这显然应该可以正确地完成我想要的转变。相反,我得到的结果是11111001。我不确定出了什么问题。会不会是signedvsunsigned char数据类型的问题?我看过的所有资源都只使用无符号数据类型。

标签: ctypesbinaryrotationbit-manipulation

解决方案


它已在其他帖子Arithmetic bit-shift on asigned integer中得到解答。要获得您期望的结果,您应该使用 unsigned char。

void right(unsigned char *c, int numRotate) {
    *c = (*c >> numRotate) | (*c << (8 - numRotate));
}

使用有符号整数右移运算符将用符号位 (MSB) 填充剩余空间,因此:

10011010 >> 4 == 11111001
01011010 >> 4 == 00000101

我链接的问题的答案表明它是编译器/平台特定的。使用移位运算代替 2 的幂的乘法/除法的常见优化技术适用于负数。例子:

#include <stdio.h>

int main()
{
    char x = -4;
    printf("0x%x -> %i\n", x, x);

    x <<= 1; //multiply by 2^1 = 2
    printf("0x%x -> %i\n", x, x);

    x >>= 2; //divide by 2^2 =4
    printf("0x%x -> %i\n", x, x);

    return 0;
}

输出:

0xfffffffc -> -4
0xfffffff8 -> -8
0xfffffffe -> -2

推荐阅读