尝试定义1,024位(128字节)位字段时出错

时间:2009-10-19 20:20:46

标签: c bit-fields

我想定义一个大的位域,以便快速监视一个非常大的元素结构的状态。以下是我到目前为止的情况:

#define TOTAL_ELEMENTS 1021

typedef struct UINT1024_tag
{
   UINT8 byte[128];
} UINT1024;

typedef struct flags_tag
{
   UINT1024:TOTAL_ELEMENTS;
} flags_t;

当我尝试编译时,我收到错误消息,“error:bit-field`< anonymous>'具有无效类型“

只能在某些类型上使用位字段吗?我认为如果我定义了一个足够大的变量,那么我的应用程序所需的大量位域就可以被定义,因为位域必须不大于用于定义它的类型。

任何想法或建议都将不胜感激。

4 个答案:

答案 0 :(得分:8)

位字段必须适合单个int,不能使用任意大小。老实说,ANSI位域实现有点破碎。它也错过了许多其他东西,比如控制实际应用程序通常需要的填充和布局。我会考虑编写一些宏或访问器函数来抽象较大的大小并放弃位域语法。

答案 1 :(得分:3)

在标准C语言中,位字段只能使用一组受限制的类型进行定义。在C89 / 90中,这些类型仅限于intsigned intunsigned int(一个鲜为人知的细节是,在此上下文中int不能保证等同于{ {1}})。在C99中,signed int已添加到受支持的集合中。任何其他类型都不能用于位字段声明。

实际上,作为一种流行的扩展,编译器通常允许在位字段声明中使用任何整数类型(或枚举类型)。但是_Bool类型......不,我不知道任何允许这样做的编译器(更不用说它似乎没有多大意义)。

答案 2 :(得分:1)

使用

 UINT128 blaha;

你没有定义一个位域。

我不确定你是否理解了bitfield是什么。我的位域是一些位。不是结构或类似的数组。你期望你的代码究竟应该做什么?

编辑:哦,我现在看到了。不,你不能使用你自己的类型,只是整理。

试试这个(未经测试的代码):

struct bit1024 {
  unsigned char byte[128];
};
struct bit1024 foo;
void
set(struct bit1024*lala, int n, int v)
{
  lala->byte[n/8] |= 1<<(n % 8);
  if (!v) {
    lala->byte[n/8] ^= 1<<(n % 8);
  }
}
int
get(struct bit1024*lala, int n)
{
  return 1 & (lala->byte[n/8] >> (n % 8));
}

答案 3 :(得分:0)

正如其他人所说,C标准不允许位字段超过其附加整数类型的大小。

我建议使用带有一些宏魔法的普通数组:

#include <limits.h>
#include <stdio.h>
#include <string.h>

// SIZE should be a constant expression
// this avoids VLAs and problems resulting from being evaluated twice
#define BITFIELD(SIZE, NAME) \
    unsigned char NAME[(SIZE) / CHAR_BIT + ((SIZE) % CHAR_BIT != 0)]

static inline void setbit(unsigned char field[], size_t idx)
{ field[idx / CHAR_BIT] |= 1u << (idx % CHAR_BIT); }

static inline void unsetbit(unsigned char field[], size_t idx)
{ field[idx / CHAR_BIT] &= ~(1u << (idx % CHAR_BIT)); }

static inline void togglebit(unsigned char field[], size_t idx)
{ field[idx / CHAR_BIT] ^= 1u << (idx % CHAR_BIT); }

static inline _Bool isbitset(unsigned char field[], size_t idx)
{ return field[idx / CHAR_BIT] & (1u << (idx % CHAR_BIT)); }

int main(void)
{
    BITFIELD(1025, foo);
    printf("sizeof foo = %u\n", sizeof foo);

    memset(foo, 0, sizeof foo);
    printf("%i", isbitset(foo, 1011));

    setbit(foo, 1011);
    printf("%i", isbitset(foo, 1011));

    unsetbit(foo, 1011);
    printf("%i", isbitset(foo, 1011));
}

希望我没有弄乱那些操作......