0

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

例如,如果我有一个数字1110 1000 0010并且我想用 替换块 2(最大块大小为 2^4)0110,我会得到0110 1000 0010. 同样,如果我想用110(max block size of 2^3) 替换块 2,我会得到111 110 000 010, 或1111 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。

4

1 回答 1

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
于 2013-10-15T03:22:34.167 回答