是否可以使用位域数组?

msc*_*msc 19 c c++ arrays struct bit-fields

我很想知道,是否可以使用位字段数组?喜欢:

struct st
{
  unsigned int i[5]: 4;
}; 
Run Code Online (Sandbox Code Playgroud)

hac*_*cks 20

不,你不能.位字段只能与整数类型变量一起使用.

C11-§6.7.2.1/ 5

位域应具有类型,它是一个合格的或不合格的版本_Bool,signed int,unsigned int,或者一些其他实现定义类型.

或者你可以这样做

struct st
{
    unsigned int i: 4;  
} arr_st[5]; 
Run Code Online (Sandbox Code Playgroud)

但它的大小将是a的5倍struct(如@ Jonathan Leffler的评论中提到的),其中5个成员各有一个位字段.所以,这里没有多大意义. 4

你可以更紧密地做到这一点

struct st
{
    uint8_t i: 4;   // Will take only a byte
} arr_st[5]; 
Run Code Online (Sandbox Code Playgroud)

  • 但是它的大小(`struct st {unsigned int i:4;} arr_st [5];`很可能是`unsigned int`大小的5倍;它不会是20位长. (8认同)

chq*_*lie 7

C不支持位域数组,所以简短的答案是否定的.

对于非常大的数组,以这种方式打包值(​​每字节2个)可能是值得的:

#define ARRAY_SIZE  1000000

unsigned char arr[(ARRAY_SIZE + 1) / 2];

int get_4bits(const unsigned char *arr, size_t index) {
    return arr[index >> 1] >> ((index & 1) << 2);
}

int set_4bits(unsigned char *arr, size_t index, int value) {
    arr[index >> 1] &= ~ 0x0F << ((index & 1) << 2);
    arr[index >> 1] |= (value & 0x0F) << ((index & 1) << 2);
}
Run Code Online (Sandbox Code Playgroud)


Tom*_*wel 5

您可以为这种情况编写自己的类。例如:

template <typename T, size_t ITEM_BIT_SIZE>
class BitArrayView {
private:
    static const size_t ARRAY_ENTRY_BITS = sizeof(T) * 8;
    static const T ITEM_MASK = (~((T) 0)) >> (ARRAY_ENTRY_BITS - ITEM_BIT_SIZE);
    T* arr;
public:
    struct ItemMutator {
        BitArrayView* owner;
        size_t index;
        T operator=(T value) {
            return owner->set(index, value);
        }
        operator T() {
            return owner->get(index);
        }
    };
    const size_t bitSize;
    BitArrayView(T* arr, size_t length) : arr(arr), bitSize((length * ARRAY_ENTRY_BITS) / ITEM_BIT_SIZE) {}
    T get(size_t index) const {
        size_t bitPos = index * ITEM_BIT_SIZE;
        size_t arrIndex = bitPos / ARRAY_ENTRY_BITS;
        size_t shiftCount = bitPos % ARRAY_ENTRY_BITS;
        return (arr[arrIndex] >> shiftCount) & ITEM_MASK;
    }
    T set(size_t index, T value) {
        size_t bitPos = index * ITEM_BIT_SIZE;
        size_t arrIndex = bitPos / ARRAY_ENTRY_BITS;
        size_t shiftCount = bitPos % ARRAY_ENTRY_BITS;
        value &= ITEM_MASK; // trim
        arr[arrIndex] &= ~(ITEM_MASK << shiftCount); // clear target bits
        arr[arrIndex] |= value << shiftCount; // insert new bits 
        return value;
    }
    ItemMutator operator[](size_t index) {
        return { this, index };
    }
};
Run Code Online (Sandbox Code Playgroud)

然后你可以像“位域”数组一样访问它:

// create array of some uints
unsigned int arr[5] = { 0, 0, 0, 0, 0 };

// set BitArrayView of 3-bit entries on some part of the array 
// (two indexes starting at 1)
BitArrayView<unsigned int, 3> arrView(arr + 1, 2);

// should equal 21 now => (2 * 32) / 3
arrView.bitSize == 21;

for (unsigned int i = 0; i < arrView.bitSize; i++) {
    arrView[i] = 7; // eg.: 0b111;
}

// now arr[1] should have all bits set
// and arr[2] should have all bits set but last one unset => (2 * 32) % 3 = 1
// the remaining arr items should stay untouched
Run Code Online (Sandbox Code Playgroud)

这是一个简单的实现,只适用于无符号支持数组。

注意operator[];) 中的“mutator 技巧” 。

当然,也可以实现其他一些运算符。