我一直在阅读 K&R C 编程语言书,但我坚持练习 2-6,内容如下:
编写一个函数 setbits(x,p,n,y) 返回 x,其中从位置 p 开始的 n 位设置为 y 的最右边 n 位,其他位保持不变。
我很难理解他们要我做什么。我在这里查看了一个可能的答案,但我仍然不太明白。我认为这是让我失望的措辞。谁能以不同的方式解释他们要我做什么?我希望不同的措辞能帮助我理解我需要在代码方面做些什么。
我一直在阅读 K&R C 编程语言书,但我坚持练习 2-6,内容如下:
编写一个函数 setbits(x,p,n,y) 返回 x,其中从位置 p 开始的 n 位设置为 y 的最右边 n 位,其他位保持不变。
我很难理解他们要我做什么。我在这里查看了一个可能的答案,但我仍然不太明白。我认为这是让我失望的措辞。谁能以不同的方式解释他们要我做什么?我希望不同的措辞能帮助我理解我需要在代码方面做些什么。
阐述Avi的回答:
int i = setbits(0xAB = b10101011, 5, 3, 0xAA = b10101010);
i equals 0x93 = b10010011
说你的 i = 0xAB。在二进制中,这是:10101011
让我们对每个位位置进行编号。
Position #: 7 6 5 4 3 2 1 0
Bit: 1 0 1 0 1 0 1 1
最右边的位(最低有效位)是位置“0”。最左边(最重要的)是位置“7”。
所以接下来的两个值 p 和 n 表示“你想修改从 p 位开始的 n 位”。因此,如果 p=5 且 n=3,您希望从第 5 位开始,总共修改 3 位。这意味着位 5、4、3。在此示例中为“101”。
Position #: 7 6 5 4 3 2 1 0
Bit: 1 0 1 0 1 0 1 1
| |
---------
(Modifying these three bits)
我们如何修改它们?我们正在替换它们。用另一组 3 位。y 中的三个最低有效位。
所以这里是y:
Position #: 7 6 5 4 3 2 1 0
Bit: 1 0 1 0 1 0 1 0
最右边的位将是位 2、1、0。或值“010”。当然,如果 n=6 的值,那么您需要将 i 中的这 6 位替换为“101010”——最右边的 6 位。
所以你的任务是从 i 中取出指定的位——在本例中为“101”——并将它们替换为 y 中的指定位——“010”。
如果你这样做,那么你的返回值是
1 0 1 0 1 0 1 0
例如:
int i = setbits(0xAB = b10101011, 5, 3, 0xAA = b10101010);
i equals 0x93 = b10010011
我们取 x (101) 中从位置 5 开始的 3 位,并将它们替换为 y (010) 中最右边的三位。
那个“可能的答案”只是没有注释的代码。难怪它没有帮助你。
问题(可能还有回答者)假设您熟悉位域。这种事情在您控制硬件寄存器的嵌入式编程中非常常见。
假设有一个寄存器可以设置音频音量级别等。同时,它可能让您选择扬声器或麦克风之类的东西。这些位可能如下所示:
ssAAAmxx——每个字母代表该数字中的一个位域。要更改音量,您必须更改“AAA”的值。现在,假设您的程序中有一些东西可以让您调节音量。这是一个简单的控件,它总是返回一个介于 0 和 7 之间的数字。其格式如下所示:
xxxxxAAA——那么你的工作就是从中获取 AAA 位(称为“y”),并将它们设置为上面的那个数字(称为“x”),而不更改不是 A 的位。因此,问题将显示为:“取 y 的最右边 3 位,并将它们设置为 x,从第 5 位开始(记住,它们从 0 开始计数)。然后,我们示例中的 3 和 5 变为 n 和 p原来的问题。
这个想法是y通常会少于n位,但如果不是,请仅使用n。用英语来说,任务是从p开始将y插入x中,使用的字段宽度为n。
从 p 位置开始,用 y 的最右边 n 位替换 x 的 n 位。
也许你应该利用getbits()
第 2.9 章中的例程
这个怎么样?
unsigned int
setbits(unsigned int x, int p, int n, unsigned int y)
{
char buffer[65];
unsigned x1 = x >> (p + 1);
x1 <<= (p + 1);
/*
* x1 now contains all the bits before position 'p'.
*/
unsigned x2 = y & ~(~0 << n);
x2 <<= (p + 1) - n;
/*
* x2 now contains the rightmost 'n' bits of 'y', left shifted (p + 1) - n bits.
*/
unsigned x3 = x & ~(~0 << ((p + 1) - n));
/*
* x3 now contains the rightmost (p + 1) - n bits.
*/
return x1 | x2 | x3;
}