代码之家  ›  专栏  ›  技术社区  ›  ntshetty

有效地在数字n中设置x位,从MSB的位置p开始

  •  0
  • ntshetty  · 技术社区  · 6 年前

    下面的代码将x位设置为从LSB开始的n个起始位置p(n是32位数字)

    //gcc 5.4.0
    #include  <stdio.h>
    unsigned int set_bits_pos(int N, int X, int P)
    {
        unsigned int mask = ((1UL << X)-1) << P; 
        return (N|mask);
    }
    
    int main(void)
    {
        unsigned int bits = 3, pos=5, num=0x0F;       
        printf("0x%X\n", set_bits_pos(num,bits,pos));
        return 0;
    }
    

    输出:

    0xEF
    

    如何将上述函数转换为设置n中的x位,从msb开始的位置p?最好的方法。谢谢

    编辑:根据建议从独立于msb和arch的32位和64位n设置

    //gcc 5.4.0
    #include  <stdio.h>
    size_t set_bits_pos(size_t N, int X, int P)
    {
        size_t mask = ((1UL << X)-1) << ((8*sizeof(N)) - P - X); 
        return (N|mask);
    }
    
    int main(void)
    {
        size_t num=0x0F;
        int bits = 3, pos=5;       
        printf("0x%X\n", set_bits_pos(num,bits,pos));
        return 0;
    }
    

    输出:

    0x0700000F
    
    1 回复  |  直到 6 年前
        1
  •  0
  •   Nominal Animal    6 年前

    我建议使用精确的宽度整数类型:

    #include <inttypes.h>
    
    uint32_t  set_low32(const uint32_t     value,
                        const unsigned int bits,
                        const unsigned int skip)
    {
        uint32_t  mask = (~(uint32_t)0) >> (32 - bits);
        return value | (mask << skip);
    }
    
    uint64_t  set_low64(const uint64_t     value,
                        const unsigned int bits,
                        const unsigned int skip)
    {
        uint64_t  mask = (~(uint64_t)0) >> (64 - bits);
        return value | (mask << skip);
    }
    
    uint32_t  set_high32(const uint32_t     value,
                         const unsigned int bits,
                         const unsigned int skip)
    {
        uint32_t  mask = (~(uint32_t)0) << (32 - bits);
        return value | (mask >> skip);
    }
    
    uint64_t  set_high64(const uint64_t     value,
                         const unsigned int bits,
                         const unsigned int skip)
    {
        uint64_t  mask = (~(uint64_t)0) << (64 - bits);
        return value | (mask >> skip);
    }
    

    bits 是要设置的位数( X 有疑问),以及 skip 是要跳过的低/高位数( P 有问题的。