C 如何用整数中的另一组半字节替换给定的半字节

C 如何用整数中的另一组半字节替换给定的半字节,c,bit-manipulation,bitwise-operators,bit-shift,bitmask,C,Bit Manipulation,Bitwise Operators,Bit Shift,Bitmask,假设您有一个整数a=0x12345678和一个短b=0xabcd 我想做的是用short b 例如:将a=0x12345678中的0,2,5,7个半字节(其中8=0个半字节、7=1个半字节、6=2个半字节等)替换为b=0xabcd(其中d=0个半字节、c=1个半字节、b=2个半字节等…) 我的方法是- 从a中清除要替换的位。 如a=0x02045070 从短的b创建掩码,如mask=0xa0b00c0d 按位或对其进行排序以获得结果结果=一个|掩码即结果=0xa2b45c7d因此替换了半字节 我

假设您有一个整数
a=0x12345678
和一个短
b=0xabcd

我想做的是用
short b

例如:
a=0x12345678
中的0,2,5,7个半字节(其中8=0个半字节、7=1个半字节、6=2个半字节等)替换为
b=0xabcd
(其中d=0个半字节、c=1个半字节、b=2个半字节等…)

我的方法是-

  • a
    中清除要替换的位。 如
    a=0x02045070
  • 从短的
    b
    创建掩码,如
    mask=0xa0b00c0d
  • 按位
    对其进行排序以获得结果<代码>结果=一个|掩码即
    结果=0xa2b45c7d
    因此替换了半字节
  • 我的问题是,我不知道从给定的
    短b

    如果你能给我一个有效的方法,这将对我有很大的帮助,我提前对此表示感谢;)

    请询问是否需要更多信息

    编辑:
    我解决问题的代码(虽然不够好)
    任何改进都将受到高度赞赏。

    int index[4] = {0,1,5,7}; // Given nibbles to be replaced in integer
    int s = 0x01024300; // integer mask i.e. cleared nibbles
        int r = 0x0000abcd; // short (converted to int )
         r = ((r & 0x0000000f) << 4*(index[0]-0)) | 
             ((r & 0x000000f0) << 4*(index[1]-1)) | 
             ((r & 0x00000f00) << 4*(index[2]-2)) |
             ((r & 0x0000f000) << 4*(index[3]-3));
        s = s|r;
    
    int索引[4]={0,1,5,7};//给定要在整数中替换的半字节
    int s=0x01024300;//整数掩码,即清除的半字节
    int r=0x0000abcd;//short(转换为int)
    
    r=((r&0x0000000f)为了能够轻松更改半字节分配,可以使用位字段联合结构:

    步骤1-创建一个允许进行半字节访问的联合

    typedef union u_nibble {
        uint32_t dwValue;
        uint16_t wValue;
        struct sNibble {
            uint32_t nib0: 4;
            uint32_t nib1: 4;
            uint32_t nib2: 4;
            uint32_t nib3: 4;
            uint32_t nib4: 4;
            uint32_t nib5: 4;
            uint32_t nib6: 4;
            uint32_t nib7: 4;
        } uNibble;
    } NIBBLE;
    
    步骤2-用整数
    a
    和短
    b
    分配两个半字节项

    NIBBLE myNibbles[2];
    uint32_t a = 0x12345678;
    uint16_t b = 0xabcd;
    
    myNibbles[0].dwValue = a;
    myNibbles[1].wValue = b;
    
    printf("a = %08x\n",myNibbles[0].dwValue);
    myNibbles[0].uNibble.nib0 = myNibbles[1].uNibble.nib0;
    myNibbles[0].uNibble.nib2 = myNibbles[1].uNibble.nib1;
    myNibbles[0].uNibble.nib5 = myNibbles[1].uNibble.nib2;
    myNibbles[0].uNibble.nib7 = myNibbles[1].uNibble.nib3;
    printf("a = %08x\n",myNibbles[0].dwValue);
    
    步骤3-通过
    b

    NIBBLE myNibbles[2];
    uint32_t a = 0x12345678;
    uint16_t b = 0xabcd;
    
    myNibbles[0].dwValue = a;
    myNibbles[1].wValue = b;
    
    printf("a = %08x\n",myNibbles[0].dwValue);
    myNibbles[0].uNibble.nib0 = myNibbles[1].uNibble.nib0;
    myNibbles[0].uNibble.nib2 = myNibbles[1].uNibble.nib1;
    myNibbles[0].uNibble.nib5 = myNibbles[1].uNibble.nib2;
    myNibbles[0].uNibble.nib7 = myNibbles[1].uNibble.nib3;
    printf("a = %08x\n",myNibbles[0].dwValue);
    
    输出将是:


    使用
    nibble=4位
    unsigned int=32位
    ,可以在unsigned int中找到一个nibble,如下所示:

    x=0x00a0b000
    ,在
    x
    中找到第三个半字节,即定位
    'b'
    。注意半字节索引以
    0
    开始

    现在第三个半字节是从
    第12位到第15位

    可以使用
    n=2^16-2^12
    选择第三个半字节。因此,在
    n
    中,第三个半字节中的所有位都将
    1
    ,其他半字节中的所有位都将
    0
    。也就是说,
    n=0x00001000

    一般来说,假设您想在二进制表示中找到一个连续的
    1
    ,其中序列从
    Xth
    位到
    Yth
    位,那么公式是
    2^(Y+1)-2^X

    #include <stdio.h>
    
    #define BUF_SIZE 33
    
    char *int2bin(int a, char *buffer, int buf_size)
    {
        int i;
        buffer[BUF_SIZE - 1] = '\0';
    
        buffer += (buf_size - 1);
    
        for(i = 31; i >= 0; i--)
        {
                *buffer-- = (a & 1) + '0';
                a >>= 1;
        }
    
        return buffer;
    }
    
    
    int main()
    {
        unsigned int a = 0;
        unsigned int b = 65535;
        unsigned int b_nibble;
        unsigned int b_at_a;
        unsigned int a_nibble_clear;
        char replace_with[8];
        unsigned int ai;
        char buffer[BUF_SIZE];
    
        memset(replace_with, -1, sizeof(replace_with));
        replace_with[0] = 0; //replace 0th nibble of a with 0th nibble of b
        replace_with[2] = 1; //replace 2nd nibble of a with 1st nibble of b
        replace_with[5] = 2; //replace 5th nibble of a with 2nd nibble of b
        replace_with[7] = 3; //replace 7th nibble of a with 3rd nibble of b
    
        int2bin(a, buffer, BUF_SIZE - 1);
        printf("a               = %s, %08x\n", buffer, a);
        int2bin(b, buffer, BUF_SIZE - 1);
        printf("b               = %s, %08x\n", buffer, b);
    
        for(ai = 0; ai < 8; ++ai)
        {
                if(replace_with[ai] != -1)
                {
                        b_nibble = (b & (1LL << ((replace_with[ai] + 1)*4)) - (1LL << (replace_with[ai]*4))) >> (replace_with[ai]*4);
                        b_at_a = b_nibble << (ai * 4);
                        a_nibble_clear = (a & ~(a & (1LL << ((ai + 1) * 4)) - (1LL << (ai * 4))));
                        a = a_nibble_clear | b_at_a;
                }
        }
    
        int2bin(a, buffer, BUF_SIZE - 1);
        printf("a               = %s, %08x\n", buffer, a);
    
    
        return 0;
    }
    
    
    Output:
    a               = 00000000000000000000000000000000, 00000000
    b               = 00000000000000001111111111111111, 0000ffff
    a               = 11110000111100000000111100001111, f0f00f0f
    
    #包括
    #定义BUF_尺寸33
    char*int2bin(inta,char*buffer,intbuf_大小)
    {
    int i;
    缓冲区[BUF_大小-1]='\0';
    缓冲区+=(buf_大小-1);
    对于(i=31;i>=0;i--)
    {
    *缓冲区--=(a&1)+“0”;
    a>>=1;
    }
    返回缓冲区;
    }
    int main()
    {
    无符号整数a=0;
    无符号整数b=65535;
    无符号整数b_半字节;
    a处的无符号整数b_;
    无符号整数a_半字节_清除;
    char将_替换为[8];
    无符号整数ai;
    字符缓冲区[BUF_大小];
    memset(用-1替换_,sizeof(用替换_));
    用[0]=0替换_;//用b的第0个半字节替换a的第0个半字节
    用[2]=1替换_;//用b的第一个半字节替换a的第二个半字节
    用[5]=2替换_;//用b的第二个半字节替换a的第五个半字节
    用[7]=3替换_;//用b的第三个半字节替换a的第七个半字节
    int2bin(a,缓冲区,BUF_大小-1);
    printf(“a=%s,%08x\n”,缓冲区,a);
    int2bin(b,缓冲区,BUF_大小-1);
    printf(“b=%s,%08x\n”,缓冲区,b);
    对于(ai=0;ai<8;++ai)
    {
    如果(将_替换为[ai]!=-1)
    {
    b_nibble=(b&(1LL)(用[ai]*4替换_);
    
    b_at_a=b_半字节半字节有4位,根据索引方案,第0半字节由位置0-3处的最低有效位表示,第一半字节由位置4-7处的最低有效位表示,依此类推

    只需将值移动到必要的量。这将在变量索引设置的位置设置半字节:

    size_t index = 5;    //6th nibble is at index 5
    size_t shift = 4 * index;    //6th nibble is represented by bits 20-23
    unsigned long nibble = 0xC;
    unsigned long result = 0x12345678;
    result = result & ~( 0xFu << shift );    //clear the 6th nibble
    result = result | ( nibble << shift );    //set the 6th nibble
    
    size\u t index=5;//第六个半字节位于索引5处
    size\u t shift=4*index;//第6个半字节由位20-23表示
    无符号长半字节=0xC;
    无符号长结果=0x12345678;
    
    result=result&~(0xFu如果我理解你的目标,你的乐趣来自于将你的填充顺序从最后数字的上半部分颠倒到下半部分。(而不是
    0,2,4,6
    ,你想要
    0,2,5,7
    )这并不难,但它确实可以让你数一数最终数字中的洞在哪里。如果我理解,那么你可以用
    0x0f0ff0f0
    遮罩,然后用
    16、12、4和0的移位填充零。例如:

    #include <stdio.h>
    
    int main (void) {
    
        unsigned a = 0x12345678, c = 0, mask = 0x0f0ff0f0;
        unsigned short b = 0xabcd;
    
        /* mask a, fill in the holes with the bits from b */
        c = (a & mask) | (((unsigned)b & 0xf000) << 16);
        c |= (((unsigned)b & 0x0f00) << 12);
        c |= (((unsigned)b & 0x00f0) << 4);
        c |= (unsigned)b & 0x000f;
    
        printf (" a : 0x%08x\n b : 0x%0hx\n c : 0x%08x\n", a, b, c);
    
        return 0;
    }
    

    如果我误解了,请告诉我,我很乐意进一步提供帮助。

    这在很大程度上取决于您在接受您的情况下的“半字节列表”
    索引[4]
    的灵活性

    您提到可以替换0到8个半字节中的任何位置。如果将半字节位作为8位位图,而不是列表,则可以将该位图用作256项表中的查找,该表将从位图映射到半字节位置为1的(固定)掩码。例如,对于半字节列表{1,3},您将拥有位图
    0b0001010
    ,它将映射到掩码
    0x0000F0F0

    然后您可以使用
    pdep
    ,它在x86上的gcc、clang、icc和MSVC上具有内部函数,以将您的short中的位扩展到正确的位置。例如,对于
    b==0xab
    ,您将拥有
    \u pdep\u u32(b,mask)==0x0000a0b0

    如果您不在