2-8 K&R C练习有何问题?

3

我是一名有帮助的助手,可以为您翻译内容。

编写一个函数rightrot(x, n),返回将整数x向右旋转n位后的值。

但是当我尝试运行它时,我得到的结果不是我期望的。

#include"stdio.h"    
int most_signficant_bit(unsigned x){
        int bitpos;
        for(bitpos = -1; x!=0;++bitpos){
            x=x>>1;
        }
        return bitpos;
    }
unsigned rightrot(unsigned x, unsigned n){
        int bitpos;
        bitpos  = most_signficant_bit(x);

       x = ((x>>n)|(((~(~0<<n))&x)<<(bitpos-n)));
        return x;
    }
int main(int argc, char const *argv[]) {
        unsigned int c1;
        c1 = 0xff1;

        printf("bitfield  %x "
        " after rightrot %x \n",c1, rightrot(c1, 4) );
        return 0;
    }

我知道(x>>n)将位域向右移动'n'次,从中复制'n'个最不重要的位,例如0000 1111 1111
(~(~0<<n))&x)复制n个最不重要的位(1111 1111 0001 & 0000 0000 1111 = 0000 0000 0001),然后将这些位移动到正确的位置<<(bitpos-n),最后用或运算符将这些位复制到x中。
但我得到的是0xff而不是0x1ff,二进制为0000 1111 1111而不是0001 1111 1111
所以问题出在哪里呢?

有趣的是,当我执行代码时,我得到的是 ff 而不是 8ff1ff - ikrabbe
是的,0x8ff 是我使用 <<(bitpos) 时的值。 - warrior
2个回答

5
 x = ((x>>n)|(((~(~0<<n))&x)<<(bitpos-n)));

您是否认为应该改为以下内容?

 x = ((x>>n)|(((~(~0<<n))&x)<<(bitpos-n+1)));

1
没错,我差点写了同样的答案..但你比我快了一分钟 +1 - Srinath

0

我认为这个表达式

x = ((x>>n)|(((~(~0<<n))&x)<<(bitpos-n+1)));

太过复杂和难以阅读。:)

此外,使用此表达式的函数实现无效,因为n可以大于类型为unsigned int的对象中的位数。

可以按照演示程序所示的以下方式编写该函数

#include <stdio.h>
#include <limits.h>

unsigned int rotate_right( unsigned int x, size_t n )
{
    const size_t N = CHAR_BIT * sizeof( int );

    n %= N;

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

int main( void )
{
    unsigned int x = 0x12345678;

    size_t n = CHAR_BIT * sizeof( int );

    do 
    { 
        printf( "%x\n", x ); 
        x = rotate_right( x, CHAR_BIT / 2 );
    } while ( n -= CHAR_BIT / 2 );
}    

程序输出为:

12345678
81234567
78123456
67812345
56781234
45678123
34567812
23456781

您可以移除头文件<limits.h>并使用以下函数计算unsigned int类型对象中的位数。
size_t bit_count()
{
    size_t n = 0;

    for ( unsigned int i = ~0u; i; i >>= 1 ) ++n;

    return n;
}

是的,这是另一种完成此练习的方法,但在K&R中仅使用了stdio.h直到本章。 - warrior
@warrior 没有问题。你可以用8替换CHAR_BIT并删除头文件。:) 或者你可以使用自己的函数most_significant_bit来计算unsigned int类型对象中位数的总数。无论哪种情况,最终函数都可以按照我展示的方式编写。 - Vlad from Moscow
好的,谢谢你的回答。你的方法很聪明,我需要学习标准库。 - warrior

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接