Unexpected C/C++ bitwise shift operators outcome

后端 未结 6 1842
攒了一身酷
攒了一身酷 2020-11-28 16:02

I think I\'m going insane with this.

I have a a piece of code that needs to create an (unsigned) integer with N consequent bits set to 1. To be exact I

6条回答
  •  忘掉有多难
    2020-11-28 16:51

    My 32 cents:

    #include 
    
    #define INT_BIT     (CHAR_BIT * sizeof(int))
    
    unsigned int set_bit_range(unsigned int n, int frm, int cnt)
    {
            return n | ((~0u >> (INT_BIT - cnt)) << frm);
    }
    

    List 1.

    A safe version with bogus / semi-circular result could be:

    unsigned int set_bit_range(unsigned int n, int f, int c)
    {
            return n | (~0u >> (c > INT_BIT ? 0 : INT_BIT - c)) << (f % INT_BIT);
    }
    

    List 2.

    Doing this without branching, or local variables, could be something like;

    return n | (~0u >> ((INT_BIT - c) % INT_BIT)) << (f % INT_BIT);
    

    List 3.

    List 2 and List 3 This would give "correct" result as long as from is less then INT_BIT and >= 0. I.e.:

    ./bs 1761 26 810
    Setting bits from 26 count 810 in 1761 -- of 32 bits
    Trying to set bits out of range, set bits from 26 to 836 in 32 sized range
    x = ~0u       =  1111 1111 1111 1111 1111 1111 1111 1111
    
    Unsafe version:
    x = x >> -778 =  0000 0000 0000 0000 0000 0011 1111 1111
    x = x <<  26  =  1111 1100 0000 0000 0000 0000 0000 0000
    x v1 Result   =  1111 1100 0000 0000 0000 0110 1110 0001
    Original:        0000 0000 0000 0000 0000 0110 1110 0001    
    
    Safe version, branching:
    x = x >>   0  =  1111 1111 1111 1111 1111 1111 1111 1111
    x = x <<  26  =  1111 1100 0000 0000 0000 0000 0000 0000
    x v2 Result   =  1111 1100 0000 0000 0000 0110 1110 0001
    Original:        0000 0000 0000 0000 0000 0110 1110 0001    
    
    Safe version, modulo:
    x = x >>  22  =  0000 0000 0000 0000 0000 0011 1111 1111
    x = x <<  26  =  1111 1100 0000 0000 0000 0000 0000 0000
    x v3 Result   =  1111 1100 0000 0000 0000 0110 1110 0001
    Original:        0000 0000 0000 0000 0000 0110 1110 0001
    

提交回复
热议问题