C++ 是否可以使用位字段数组?

C++ 是否可以使用位字段数组?,c++,c,arrays,struct,bit-fields,C++,C,Arrays,Struct,Bit Fields,我很想知道,可以使用位字段数组吗?比如: struct st { unsigned int i[5]: 4; }; 不,你不能。位字段只能与整型变量一起使用 C11-§6.7.2.1/5 位字段的类型应为合格或不合格版本的\u Bool,有符号整数,无符号整数,或其他实现定义的类型 或者你也可以这样做 struct st { unsigned int i: 4; } arr_st[5]; struct st { uint8_t i: 4; // Will ta

我很想知道,可以使用位字段数组吗?比如:

struct st
{
  unsigned int i[5]: 4;
}; 

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

C11-§6.7.2.1/5 位字段的类型应为合格或不合格版本的
\u Bool
有符号整数
无符号整数
,或其他实现定义的类型

或者你也可以这样做

struct st
{
    unsigned int i: 4;  
} arr_st[5]; 
struct st
{
    uint8_t i: 4;   // Will take only a byte
} arr_st[5]; 
但是它的大小将是一个
结构的5倍(如@中所述),该结构有5个成员,每个成员的位字段
4
。所以,这在这里没有多大意义

更接近于你可以做到这一点

struct st
{
    unsigned int i: 4;  
} arr_st[5]; 
struct st
{
    uint8_t i: 4;   // Will take only a byte
} arr_st[5]; 

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);
}
#定义数组大小1000000
无符号字符arr[(数组大小+1)/2];
int get_4位(常量无符号字符*arr,大小索引){

返回arr[index>>1]>>((index&1)>1]&=~0x0f1]|=(value&0x0F)您可以为这种情况编写自己的类。例如:

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 };
    }
};
模板
类BitArrayView{
私人:
静态常量大小\u t数组\u条目\u位=sizeof(t)*8;
静态常量T ITEM_MASK=(~(T)0))>>(数组项位-ITEM位大小);
T*arr;
公众:
结构项变换器{
BitArrayView*所有者;
尺寸指数;
T运算符=(T值){
返回所有者->设置(索引、值);
}
算子T(){
返回所有者->获取(索引);
}
};
常量大小\u t比特大小;
BitArrayView(T*arr,size\u T length):arr(arr),bitSize((length*ARRAY\u ENTRY\u BITS)/ITEM\u BIT\u size){}
T获取(大小索引)常量{
大小\u t比特位置=索引*项目\u比特\u大小;
大小\u t数组索引=位位置/数组\u条目\u位;
size\u t shiftCount=bitPos%数组\u条目\u位;
返回(arr[ARRDINDEX]>>移位计数)和项目掩码;
}
T集(大小索引,T值){
大小\u t比特位置=索引*项目\u比特\u大小;
大小\u t数组索引=位位置/数组\u条目\u位;
size\u t shiftCount=bitPos%数组\u条目\u位;
值&=ITEM_MASK;//修剪
arr[arrIndex]&=~(ITEM_-MASK(2*32)%3=1
//剩余的arr项目应保持不变
这是一个简单的实现,应该只适用于无符号的支持数组

请注意
操作符[]
;)中的“变异技巧”


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

但是该运算符的大小(
struct st{unsigned int i:4;}arr_st[5]
很可能是无符号int的5倍;它不会有20位长。@JonathanLeffler;是的。但是没有其他方法来声明位字段数组。@haccks谢谢你的帮助。type
uint8_t
可能不可用。
struct st{unsigned char i:4;}arru st[5]
或只是
无符号字符arr[5];
似乎更可取。@IlmariKaronen;我的意思是说struct
arr\st
将是
struct-like
struct-stt{无符号int I:4;无符号int j:4;无符号int k:4;无符号int l:4;无符号int m:4;}s;
请注意,最新的C代码不再使用位字段。一个有用的替代方法是使用位掩码字段,并对其执行按位操作。顺便说一句,编译器会生成等效的代码。@basilestrynkevitch:我想知道这是从何而来的。使用位字段比使用按位操作处理位掩码字段更不容易出错口粮。