0

现在我正在阅读《计算机系统:程序员视角》这本书。

书中的一个问题是对有符号整数执行逻辑右移,我不知道如何开始。

以下是书中的实际问题:

填写以下 C 函数的代码。

  • 函数srl使用算术右移(由 value 给出xsra)执行逻辑右移,然后执行不包括右移或除法的其他操作。

  • 函数sra使用逻辑右移(由 value 给出xsrl)执行算术右移,然后执行不包括右移或除法的其他操作。

您可以使用计算8*sizeof(int)来确定w数据类型中的位数int。移位量的k范围可以从0w − 1

unsigned srl(unsigned x, int k) {
    /* Perform shift arithmetically */
    unsigned xsra = (int) x >> k;
    .
    .
    .
}

int sra(int x, int k) {
    /* Perform shift logically */
    int xsrl = (unsigned) x >> k; 
    .
    .
    .
}

我希望你现在明白这个问题。

4

2 回答 2

2

我不会给你一个完整的答案,因为这显然是家庭作业,但我会给你一些提示来帮助你自己解决这个问题:

  • 对于 N 位的逻辑右移,您需要在算术移位后清除结果的前 N ​​位

  • 您可以通过应用适当的掩码来清除值中的位,通常使用按位 AND 或 XOR

  • 要清除一个值的前 N ​​位,您需要一个带有 N 0 和剩余位 1 的掩码

  • 您可以使用按位左移生成合适的掩码W - N,其中 W 是一个单词中的位数(您可以计算为W = sizeof(int) * CHAR_BIT;

例如,逻辑右移 2

value              = 10001010
value >>= 2        = 11100010     // arithmetic right shift

mask               = 00111111     // mask has top 2 bits set to 0

value & mask       = 00100010     // apply mask to get logical right shift

最棘手的部分是生成掩码,但如果您考虑应用左移这样一个合适的值,然后可能再进行一次按位运算,您应该很快就会看到一个相当简单的解决方案。

于 2013-07-27T06:58:01.697 回答
0

按照保罗的建议,我花了一点时间来制作面具。但我创建它如下。

首先我左移 1 如下

1 << (sizeof(int)*8-k);

如果我认为 k 为 10 并且 INT 大小为 32 我将得到以下掩码

   00000000010000000000000000000000 ( 1 at 23 rd position 32 - 10 = 22 )

然后加上 -1 (0xffffffff)

   00000000010000000000000000000000
 + 11111111111111111111111111111111
 +++++++++++++++++++++++++++++++++++

   00000000001111111111111111111111 --> required mask with first 10 bits set to 

与算术移位的结果相加将给出逻辑移位结果。

以下是C代码

unsigned srl(unsigned x, int k) {
/* Perform shift arithmetically */
        unsigned xsra = (int) x >> k;
    int mask = (1 << (sizeof(int)*8-k)) + -1;
    int result = xsra & mask;
}

它有效。

于 2013-07-27T19:07:33.123 回答