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

从C中的字节数组中提取最后N位

  •  0
  • Du6  · 技术社区  · 3 年前

    我有一个用C表示的无符号字符数组:

    unsigned char array[] = { 0xF0, 0xCC, 0xAA, 0xF0}; 
    /* Represented as binary: 11110000 11001100 10101010 11110000 */
    
    

    我想从这个数组中提取最后N个比特,并将它们存储在一个整数中。例如,如果我想提取最后5位,结果应该是:

    int i = 32; /* Represented as binary: 10000 */
    

    我试着使用BIGNUM库,但我发现它在这方面做得太过火了,而且有点慢。在C中有没有更有效的方法来实现这一点?

    所附代码:

    unsigned char array[] = { 0xF0, 0xCC, 0xAA, 0xF0}; 
    int i = 0; 
    int j;
    int totalBits = sizeof(array) * 8;  
    int startBit = totalBits - 5;  
    
    for (j = startBit; j < totalBits; j++) 
    {
                i = i << 1;
                i = i | (array[j] & 1);
    }    
    
    
    1 回复  |  直到 3 年前
        1
  •  2
  •   Fe2O3    3 年前

    英勇的努力!感谢您展示您的尝试。

    我在你的版本中添加了一些评论:

    unsigned char array[] = { 0xF0, 0xCC, 0xAA, 0xF0}; 
    int i = 0; 
    int j;
    int totalBits = sizeof(array) * 8;  // currently meaning 32
    int startBit = totalBits - 5;  // meaning 27 where '5' is the magic number wanted
    
    for (j = startBit; j < totalBits; j++) 
    {
                i = i << 1;
                i = i | (array[j] & 1); // Oops! there is no array[27]! Top element is array[3]!
    }    
    

    以下是一个似乎有效的版本的粗略草案:

    int main(void) {
        unsigned char arr[] = { 0xF0, 0xCC, 0xAA, 0xF0 }; // Your array (add more! Try it out!)
    
        union { // providing for up to N = 64bits (on my system)
            unsigned char c[8];
            unsigned long l;
        } foo;
    
        foo.l = 0; // initialise
    
        size_t sz = sizeof arr / sizeof arr[0]; // source byte count
        size_t n = 0; // destination byte count
    
        // wastefully copy as many bytes as are available until 'foo' is a full as possible
        // Notice the 'endian-ness' of index n going from 0 to 8.
        // Other hardware could change this to count downward, instead.
        for( size_t i = sz; i && n < sizeof foo; ) {
            foo.c[ n++ ] = arr[ --i ]; // grab one byte
            printf( "%x\n", foo.l ); // debugging
        }
    
        int N = 5;
        foo.l &= (1<<N)-1; // Mask off the low order N bits from that long
    
        printf( "%x\n", foo.l );
    
        return 0;
    }
    

    希望这能有所帮助。

    逾期警告:的最大值 N ,在此代码中,为 63 …应该加上检查 N 不超过蓄能器的宽度 foo ,如果 N 正是这个数字,绕过移位和掩码操作。。。

    附言:当玩比特操作时,使用它通常更安全 unsigned 数据类型。一些C实现显然反对符号位被不适当地篡改。