用两点之间的新位替换旧位

时间:2014-09-14 21:57:24

标签: c bit

我想将oldValuehi之间的lo位更改为newValuehi之间的lo位(保持其他位不变)。一个好的起点是什么?

伪代码将是最有帮助的!

int setField (int oldValue, int hi, int lo, int newValue) {     
    int x = 0;  
    if(lo > hi){
        int temp = lo;
        lo = hi;
        hi = temp;
    } 
}

1 个答案:

答案 0 :(得分:1)

首先,您应该从此函数返回一些结果或通过引用传递它,以便所做的任何更改都可以反映在函数之外。

一个好的起点可能是检查 this tutorial 的按位操作,它的解释很好,它将为解决这些类型的问题提供更多的理解。

现在回到我们的问题。首先,让我们通过一个例子澄清问题所在:

从位lo=2插入位hi=6oldValue = 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

现在为hiunsigned位部分创建左右掩码。您需要了解 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,我们需要清除 oldValuelo之间的位,其中来自hi的位将是插入

newValue的{​​{1}}至lo位之外的所有内容(仅hinewValue中的位将保持清除状态的掩码将保持原样lo,所有其他人将为0(已清除)):

hi

使用newValueint clear_mask1 = left_mask & right_mask; 的示例值:

lo=2

清除hi=6的{​​{1}}到clear_mask1 = 00000000000000000000000001111100 ^ ^ hi lo 位的掩码(lohi之间的所有位变为0):

oldValue

使用lohi的示例值:

int clear_mask2 = ~(left_mask & right_mask);

现在,您清除lo=2左侧的hi=6左侧,按位按<和> 它的掩码:

clear_mask2 = 11111111111111111111111110000011
                                       ^   ^
                                       hi  lo

使用我们的lo示例:

hi

然后清除newValuenewValue &= clear_mask1; newValue=127之间的位,按按位&和清除它的掩码:

newValue = 00000000000000000000000001111100
                                    ^   ^
                                    hi  lo

使用我们的lo示例:

hi

最终结果将是oldValueoldValue &= clear_mask2; 之间的按位或

oldValue=1024

我们得到oldValue = 00000000000000000000010000000000 ^ ^ hi lo :)

的价值

解决方案代码:

oldValue

对于上面的示例,此代码返回newValue

正在运行代码 here