[HW问题的一部分]
假设2的补码,32位字长。只允许使用signed int和常量0到0xFF。我被要求通过&#34; n&#34;来实现逻辑右移。比特(0 <= n <= 31)仅使用运算符: ! 〜&amp; ^ | +&lt;&lt; &GT;&GT;
我想我可以存储和清除符号位,执行移位,并将存储的符号位替换为新位置。
我想实施手术&#34; 31 - n&#34; (没有使用&#34; - &#34;运算符)来找到移位后存储的符号位的适当位置。
如果n是正数,我可以使用表达式:&#34; 31 +(~n + 1)&#34;但是我不相信这在n = 0的情况下会起作用。
这是我到目前为止所拥有的:
int logicalShift(int x, int n) {
/* Store & clear sign bit, perform shift, and replace stored sign bit
in new location */
int bit = (x >> 31) & 1; // Store most significant bit
x &= ~(1 << 31); // Clear most significant bit
x = x >> n; // Shift by n
x &= ~((~bit) << (31 - n)); // Replace MSbit in new location
return x;
}
感谢任何帮助和/或提示。
答案 0 :(得分:0)
[编辑:已解决]
感谢大家的帮助。在这种情况下,~n + 1用于否定n,包括n = 0的情况(其中它根据需要返回0)。功能代码如下(绝不是最优雅的解决方案)。实用程序操作借鉴于:How do you set, clear, and toggle a single bit?
int logicalShift(int x, int n) {
/* Store & clear sign bit, perform shift, and replace stored sign bit
in new location */
int bit = (x >> 31) & 1; // Store most significant bit
x &= ~(1 << 31); // Clear most significant bit
x = x >> n; // Shift by n
x ^= ((~bit + 1) ^ x) & (1 << (31 + (~n + 1))); // Replace MSbit in new location
return x;
}
答案 1 :(得分:0)
一个简单的解决方案是
int logicalShift(int x, int n) {
return (x >> n) ^ (((x & 0x80000000) >> n) << 1);
}
遗憾的是,禁止使用常量0x80000000
。我们可以将其计算为1 << 31
(忽略C中未定义的行为),或者为节省指令,将31 - n
计算为n ^ 31
,然后使用以下更为人为的方法:
int logicalShift(int x, int n) {
int b = 1 << (n ^ 31);
return b ^ ((x >> n) + b);
}