【问题标题】:Generic circular bitwise shift behavior通用循环位移行为
【发布时间】:2015-07-05 08:10:27
【问题描述】:

这里有很多关于循环位移行为的问题;然而,即使在经历了这些之后,我认为下面的陈述没有被任何人提出,我对此感到有点困惑。

来自维基百科的Circular Shift 声明:

/*
 * Shift operations in C are only defined for shift values which are
 * not negative and smaller than sizeof(value) * CHAR_BIT.
 */

unsigned int rotl(unsigned int value, int shift) {
    return (value << shift) | (value >> (sizeof(value) * CHAR_BIT - shift));
}

unsigned int rotr(unsigned int value, int shift) {
    return (value >> shift) | (value << (sizeof(value) * CHAR_BIT - shift));
}

我对上面几行的解释是——在上面提到的两个换档行为条件下是不确定的。

但是我看到给出的例子

rotl(0x8000, -1) 回复0x00010000

rotl(8,-1) 回复16

处理此类移位参数(即负数和大于位数)的正确方法是什么?我是不是误解了什么?

【问题讨论】:

  • 第二个例子与第一个例子相矛盾。我认为第二个函数调用的结果应该是 16 而不是 4。
  • @VladfromMoscow - 是的,我编辑了答案 - 但我已将示例作为参考 - 我的主要困惑点是部分 - 根据该部分,如果移位值为 -ve - 行为应该未定义 -你能帮我理解吗?
  • 如果进行右移(&gt;&gt;),RHS 上的值必须介于 0 和值中的位数减一之间;如果您进行左移,则 RHS 上的值必须介于 0 和值中的位数减一之间。因此,您可以将一个方向定义为正方向,将另一个方向定义为负方向,并通过一个函数调用来管理它们,该函数调用接受一个正参数或负参数,并通过适当的移位操作将负值转换为正值。看起来rotl 函数希望负值向左移动——这是一个合理但随意的选择。
  • ...既然代码添加到问题中,很容易看出维基百科上rotl()的版本只能合法调用shift的值在0到31之间(如果 unsigned int 是 32 位值)。任何用负值调用它的尝试都会导致未定义的行为。您没有显示使用负转移的示例从哪里获得 - 它似乎不是维基百科。可能有一个rotl 的实现,它测试shift 的值是正还是负,并使用rotl()rotr() 中显示的表达式中的一个或另一个来实现所需的结果。
  • @JonathanLeffler - 实际上注意到我指的是直接显示答案 - 但我想你的答案和为模运算提供的其他答案我明白当 shift 的值是这两个条件之一时该怎么做 -感谢您的帮助

标签: c bit-manipulation bit-shift


【解决方案1】:
#define CHAR_BITS  ( 8 )
#define UINT_BITS  ( sizeof(unsigned int) * CHAR_BITS )

// We need modulo, not remainder. This is a way to obtain it.
int mod(int x, int m) {
    return ((x % m) + m) % m;
}

// Calculate left rotation for any shift value.
unsigned int rotl(unsigned int value, int shift) {
    int lshift = mod(shift, UINT_BITS);
    return (value << lshift) | (value >> (UINT_BITS - lshift));
}

【讨论】:

  • 所以基本上是为了克服违反条件移位大于位数的问题 - 我们执行模运算以获得所需的效果
  • 没错。我们保持在允许的shift 范围内,但我们正确地获得了预期的结果。
  • 这就是建议的解决方案;这是处理它的一种有效方法。由于UINT_BITS 的值将是 2 的幂,因此您可能可以使用位掩码而不是双模运算 - 但如果您愿意接受负移位,则必须小心。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-25
相关资源
最近更新 更多