位操作 - 替换“块”

时间:2013-10-15 02:20:30

标签: bit-manipulation

我正在尝试编写一个函数,用一个新值替换大小为2 ^ x的某个“块”。

例如,如果我有一个数字1110 1000 0010并且我想用0110替换第2块(最大块大小为2 ^ 4),我会得到0110 1000 0010。同样,如果我希望用110替换块2(最大块大小为2 ^ 3),我会得到111 110 000 0101111 1000 0010

replace_block (value, x, blockNumber, newValue) {
    value |= ((value >> (blockNumber*x) & ~((1 << x) – 1)) | newValue) << (blockNumber*x)
}

Step by step process of what I'm trying to do with this code:
1. Shift the block we want all the way to the right
2. Mask that block with 0's
3. Mask that block again, but with the new value we want
4. Shift the block all the way back to the original position
5. Or the bits in the block with the original value

这是我到目前为止所做的,但我不认为这是正确的。

注意:最右边的块是块0。

1 个答案:

答案 0 :(得分:2)

首先我们需要掩码:掩码是一组“块大小”广泛移位到右侧块。

  • 一组“块大小”宽:(1<<size) - 1
  • 一组“块大小”广泛移位到正确位置:((1<<size)-1) << (number*size)

首先,我们清除将被替换的位置中的位,然后我们将其保留在我们想要的位中。

  • 清除掩码位的旧值:oldv & ~mask
  • 新值转移到了正确的位置:newv << (number*size)
  • 新值转移到正确的位置并屏蔽到右边宽度:(newv<<(number*size)) & mask
  • 清除旧位并插入新值:(oldv&~mask) | ((newv<<(number*size))&mask)

所以你想要的代码是:

    mask=(((1<<size)-1)<<(number*size));
    result=((oldv&~mask)|((newv<<(number*size))&mask));

测试程序:

    #include <stdio.h>

    void printbits(int n) {
        unsigned int i = 1<<(sizeof(n) * 8 - 1);
        while (i > 0) {
            if (n & i)
                 printf("1");
            else
                 printf("0");
            i >>= 1;
        }
    }

    int main(void) {

        int size,number,mask,oldv,newv,result;

        size=4;number=2;oldv=0;newv=15;
        mask=(((1<<size)-1)<<(number*size));
        result=((oldv&~mask)|((newv<<(number*size))&mask));
        printf("\nsize   = %d\nnumber = %d",size,number);
        printf("\noldv   = "); printbits(oldv);
        printf("\nnewv   = "); printbits(newv);
        printf("\nmask   = "); printbits(mask);
        printf("\nomask  = "); printbits(oldv&~mask);
        printf("\nnmask  = "); printbits((newv<<(number*size))&mask);
        printf("\nresult = "); printbits(result);
        printf("\n");

        size=4;number=2;oldv=~0;newv=0;
        mask=(((1<<size)-1)<<(number*size));
        result=((oldv&~mask)|((newv<<(number*size))&mask));
        printf("\nsize   = %d\nnumber = %d",size,number);
        printf("\noldv   = "); printbits(oldv);
        printf("\nnewv   = "); printbits(newv);
        printf("\nmask   = "); printbits(mask);
        printf("\nomask  = "); printbits(oldv&~mask);
        printf("\nnmask  = "); printbits((newv<<(number*size))&mask);
        printf("\nresult = "); printbits(result);
        printf("\n");

        size=3;number=2;oldv=0;newv=7;
        mask=(((1<<size)-1)<<(number*size));
        result=((oldv&~mask)|((newv<<(number*size))&mask));
        printf("\nsize   = %d\nnumber = %d",size,number);
        printf("\noldv   = "); printbits(oldv);
        printf("\nnewv   = "); printbits(newv);
        printf("\nmask   = "); printbits(mask);
        printf("\nomask  = "); printbits(oldv&~mask);
        printf("\nnmask  = "); printbits((newv<<(number*size))&mask);
        printf("\nresult = "); printbits(result);
        printf("\n");

        size=3;number=2;oldv=~0;newv=0;
        mask=(((1<<size)-1)<<(number*size));
        result=((oldv&~mask)|((newv<<(number*size))&mask));
        printf("\nsize   = %d\nnumber = %d",size,number);
        printf("\noldv   = "); printbits(oldv);
        printf("\nnewv   = "); printbits(newv);
        printf("\nmask   = "); printbits(mask);
        printf("\nomask  = "); printbits(oldv&~mask);
        printf("\nnmask  = "); printbits((newv<<(number*size))&mask);
        printf("\nresult = "); printbits(result);
        printf("\n");

        size=4;number=4;oldv=0xAAAAAAAA;newv=0x15;
        mask=(((1<<size)-1)<<(number*size));
        result=((oldv&~mask)|((newv<<(number*size))&mask));
        printf("\nsize   = %d\nnumber = %d",size,number);
        printf("\noldv   = "); printbits(oldv);
        printf("\nnewv   = "); printbits(newv);
        printf("\nmask   = "); printbits(mask);
        printf("\nomask  = "); printbits(oldv&~mask);
        printf("\nnmask  = "); printbits((newv<<(number*size))&mask);
        printf("\nresult = "); printbits(result);
        printf("\n");

        size=5;number=3;oldv=0xAAAAAAAA;newv=0x15;
        mask=(((1<<size)-1)<<(number*size));
        result=((oldv&~mask)|((newv<<(number*size))&mask));
        printf("\nsize   = %d\nnumber = %d",size,number);
        printf("\noldv   = "); printbits(oldv);
        printf("\nnewv   = "); printbits(newv);
        printf("\nmask   = "); printbits(mask);
        printf("\nomask  = "); printbits(oldv&~mask);
        printf("\nnmask  = "); printbits((newv<<(number*size))&mask);
        printf("\nresult = "); printbits(result);
        printf("\n");

        return 0;
    }

结果:

    size   = 4
    number = 2
    oldv   = 00000000000000000000000000000000
    newv   = 00000000000000000000000000001111
    mask   = 00000000000000000000111100000000
    omask  = 00000000000000000000000000000000
    nmask  = 00000000000000000000111100000000
    result = 00000000000000000000111100000000

    size   = 4
    number = 2
    oldv   = 11111111111111111111111111111111
    newv   = 00000000000000000000000000000000
    mask   = 00000000000000000000111100000000
    omask  = 11111111111111111111000011111111
    nmask  = 00000000000000000000000000000000
    result = 11111111111111111111000011111111

    size   = 3
    number = 2
    oldv   = 00000000000000000000000000000000
    newv   = 00000000000000000000000000000111
    mask   = 00000000000000000000000111000000
    omask  = 00000000000000000000000000000000
    nmask  = 00000000000000000000000111000000
    result = 00000000000000000000000111000000

    size   = 3
    number = 2
    oldv   = 11111111111111111111111111111111
    newv   = 00000000000000000000000000000000
    mask   = 00000000000000000000000111000000
    omask  = 11111111111111111111111000111111
    nmask  = 00000000000000000000000000000000
    result = 11111111111111111111111000111111

    size   = 4
    number = 4
    oldv   = 10101010101010101010101010101010
    newv   = 00000000000000000000000000010101
    mask   = 00000000000011110000000000000000
    omask  = 10101010101000001010101010101010
    nmask  = 00000000000001010000000000000000
    result = 10101010101001011010101010101010

    size   = 5
    number = 3
    oldv   = 10101010101010101010101010101010
    newv   = 00000000000000000000000000010101
    mask   = 00000000000011111000000000000000
    omask  = 10101010101000000010101010101010
    nmask  = 00000000000010101000000000000000
    result = 10101010101010101010101010101010