在C语言中设置位

5
我想要完成以下内容:
编写一个名为 setbits(x,p,n,y) 的函数,将位于位置 p 右侧的右侧 n 个位设置为 y 的最右边的 n 个位,并保留其他位不变。函数应该返回修改后的 x
我已经尝试了类似下面的代码,但是得不到正确的答案。请问我的错误在哪里?
unsigned setbits(unsigned x,int p,int n,unsigned y)
{
    return (x>>p & (y|(~0<<n)));
}

1
首先,在编写位运算 C 代码时,使用带有有用名称的临时变量是个好主意,可以帮助你看清楚自己在做什么。编译器可能会优化掉它们,但源代码的可读性将保持不变。 - Misha
我已经编辑了函数,使得它可以将x作为参数传入。 - user1413523
6
作业?是吗? - Ed Heal
1
@Ed Heal:这不是作业,而是我在学习C语言中的位运算,并在一本书中遇到了这个问题。我尝试了一下,但不确定我的方法是否正确,结果也是错误的。所以我请求帮助。 - user1413523
在这里阅读我的答案:将n到m位设置为1 - Grijesh Chauhan
显示剩余3条评论
4个回答

3

类似于:

unsigned setbits(unsigned x,int p,int n,unsigned y)
{
    unsigned mask = (1U << n) - 1U; // n-bits
    y &= mask; // rightmost n bits of y
    y <<= p;   // which begin at position p
    mask <<= p; //idem
    x &= ~mask; //set the 0s
    x |= y;     //set the 1s
    return x;
}

如果你想用更少的代码行实现,这样会更难调试,但是会更酷炫:

unsigned setbits(unsigned x,int p,int n,unsigned y)
{
    unsigned mask = (1U << n) - 1U; // n-bits
    return (x & ~(mask << p)) | ((y & mask) << p);
}

1
获取 y 的最后 n 位:(将得到一个最后 n 位等于 y,其余位设置为零的数字)
last_n_bits_of_y = y & (((1<<(n+1))-1);

然后我们可以通过(32-n-p+1)来抵消它(请检查!)

last_n_bits_of_y_offset = last_n_bits_of_y << (32-n-p+1);

现在我们擦除我们想要更改的x的位:

new_x = x & (~( (((1<<(n+1))-1) << (32-n-p+1) ) );

并填充它与我们的位:

new_x = new_x & last_n_bits_of_y_offset;

就是这样!我没有真正测试过它,但希望你能理解。


1
你所有的 && 可能都应该改成 & - Oleg2718281828

1
  1. 在您的函数中,您使用 x>>() 使您失去了右侧的 x 个位数,并且从未在以后恢复它们。
  2. 只使用 & 是无法设置位,因为结果取决于两个操作数,除非您知道其中一个操作数仅由 1 组成。
  3. (y|(~0<<n)) 用于从 y 中截取位,但这次不适合使用 |,请使用 & 和适当的第二个操作数。

这是解决方法(我敢赌有更短的方法,但这是直接明了的):

(x & ~(~(~0<<n)<<p) | (y&~(~0<<n)) << p);

左部分的|清除x中位置p处的n位,并且右部分带来y位。


1

我不知道我的眼睛还是我的大脑更疼。无论如何,+1 :p - Corbin
1
可怜的家伙得维护这个:D - RedX
// 它是一个开源的编程语言,其语法类似于C语言。 - Potatoswatter

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