【问题标题】:Bit rotation with signed char (C)?带符号字符(C)的位旋转?
【发布时间】:2019-03-24 22:57:14
【问题描述】:

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

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

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

【问题讨论】:

  • 有符号或无符号数据类型的事实与位顺序无关。好吧,除非您对其进行算术运算,例如上面的减法。移位等按位运算不考虑符号
  • 转换前将*c 转换为unsigned char。您的编译器对有符号类型进行算术右移,而普通的 char 似乎是您机器上的有符号类型。 (*c = ((unsigned char)(*c) &gt;&gt; numRotate) | ((unsigned char)(*c) &lt;&lt; (8 - numRotate));)
  • @mangusta 确实与*c 已签名有关。有符号变量的右移是实现定义的。轮班前将其发送至unsigned char
  • @AlexLop 你的意思是C标准库的实现吗?我想如果我们将 11111111(一种字节大小的数据类型)向左移动一次,无论符号是什么,我们都会得到 11111110。 OP 抱怨她得到的位模式,而不是它的数值

标签: c types binary rotation bit-manipulation


【解决方案1】:

右移负值具有实现定义的行为。如果 char 是 8 位宽并且默认在您的平台上签名,则模式 10011010 具有负值。您必须使用 unsigned char 来为您的目的定义行为:

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

【讨论】:

    【解决方案2】:

    已在其他帖子Arithmetic bit-shift on a signed 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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-21
      • 1970-01-01
      • 2018-08-28
      • 1970-01-01
      • 2015-10-27
      相关资源
      最近更新 更多