C中的循环移位,意外行为

时间:2013-12-05 01:12:14

标签: c bit-shift kernighan-and-ritchie

我目前正在使用The C Programming Language(K& R)[练习2.8]进行练习,以编写一个正确的循环移位函数来旋转整数x,n个位置。

我相信我已经提出了一个解决方案,但出于一些奇怪的原因,当我超出单词长度时(即100位移位),当我相信我不应该这样做时,我仍然会得到正确的答案。 ; t代码如下。

#include <stdio.h>

unsigned rightrot(unsigned x, int n);

int main(void)
{
    printf("%u\n", rightrot(1,100));  /* this should yield zero (overshift) */
    return 0;
}

unsigned rightrot(unsigned int x, int n)
{
    unsigned a = ~0;
    int i;

    for (i = 1; a > 1; ++i)     /* calculating the word length */
        a = a/2;

    return (x >> n) | (x << (i-n));
}

线上的变化:

return (x >> n) | (x << (i-n));

应该在离开0 | 0时将所有二进制数字移出我认为,当传递的移位大小大于字长时。但令我惊讶的是,这段代码返回的答案完全相同,就好像我使用的是允许大于字长的n的以下版本:

return (x >> (n % i)) | (x << ((i-n) % i);

记住i是单词长度。

我正在使用带有-std = c89和-pedantic-errors的gcc 4.7.2,并且也没有得到任何警告。

2 个答案:

答案 0 :(得分:3)

在UNDEFINED中移动超过C中的单词大小,所以任何事情都可能发生。在大多数机器上,使用具有log 2 字大小选择位的多路复用树完成移位,忽略移位计数的较高位,因此在32位机器上移位100可能是与4的班次相同。但你可能得到任何东西,包括崩溃。

答案 1 :(得分:3)

如果n大于i,则i - n为否定。使用带有负数的<<运算符作为右操作数是未定义的行为。