我想将oldValue
和hi
之间的lo
位更改为newValue
和hi
之间的lo
位(保持其他位不变)。一个好的起点是什么?
伪代码将是最有帮助的!
int setField (int oldValue, int hi, int lo, int newValue) {
int x = 0;
if(lo > hi){
int temp = lo;
lo = hi;
hi = temp;
}
}
答案 0 :(得分:1)
首先,您应该从此函数返回一些结果或通过引用传递它,以便所做的任何更改都可以反映在函数之外。
一个好的起点可能是检查 this tutorial 的按位操作,它的解释很好,它将为解决这些类型的问题提供更多的理解。
现在回到我们的问题。首先,让我们通过一个例子澄清问题所在:
从位lo=2
插入位hi=6
。
oldValue = 1024
(以二进制波纹显示)
newValue = 127
(以二进制波纹显示)
result = 1148
(以二进制文件显示)
oldValue: 0000000000000000000001000[00000]00
^ ^
hi lo
newValue: 0000000000000000000000000[11111]11
^ ^
hi lo
现在我们将lo
中的所有位从hi
移至newValue
,并将lo
中的hi
中的oldValue
插入result: 0000000000000000000001000[11111]00
^ ^
hi lo
int all_ones = ~0; /* 11111111111111111111111111111111 */
现在,实现目标的一种方法是:
创建所有1的数字。因为它是一个整数,所以它的大小是32位,所以会有32个1:
lo
现在为hi
和unsigned
位部分创建左右掩码。您需要了解 bit-shifting 才能理解以下说明。
执行逻辑右移(请注意int right_mask = ((unsigned int)all_ones >> (32 - hi - 1));
)以获取正确的掩码:
hi=6
对于right_mask = 00000000000000000000000001111111
^
hi
我们让所有人向右移动了25个位置:
int left_mask = (all_ones << lo);
执行逻辑左移以获取左侧遮罩:
lo=2
对于right_mask = 11111111111111111111111111111100
^
lo
我们让所有人向左移动了两个位置:
newValue
然后使用左右掩码获取用于隔离所需位的掩码。
对于lo
,我们需要清除除{/ 1}}到hi
之外的所有位,因为这些位将插入{ {1}}。
对于oldValue
,我们需要清除 oldValue
到lo
之间的位,其中来自hi
的位将是插入
除newValue
的{{1}}至lo
位之外的所有内容(仅hi
至newValue
中的位将保持清除状态的掩码将保持原样lo
,所有其他人将为0(已清除)):
hi
使用newValue
和int clear_mask1 = left_mask & right_mask;
的示例值:
lo=2
清除hi=6
的{{1}}到clear_mask1 = 00000000000000000000000001111100
^ ^
hi lo
位的掩码(lo
和hi
之间的所有位变为0):
oldValue
使用lo
和hi
的示例值:
int clear_mask2 = ~(left_mask & right_mask);
现在,您清除lo=2
左侧的hi=6
左侧,按位按<和> 它的掩码:
clear_mask2 = 11111111111111111111111110000011
^ ^
hi lo
使用我们的lo
示例:
hi
然后清除newValue
中newValue &= clear_mask1;
和newValue=127
之间的位,按按位&和清除它的掩码:
newValue = 00000000000000000000000001111100
^ ^
hi lo
使用我们的lo
示例:
hi
最终结果将是oldValue
和oldValue &= clear_mask2;
之间的按位或。
oldValue=1024
我们得到oldValue = 00000000000000000000010000000000
^ ^
hi lo
:)
解决方案代码:
oldValue
对于上面的示例,此代码返回newValue
正在运行代码 here