4

我想定义一个大的位域,以便快速监控非常大的元素结构的状态。这是我到目前为止所拥有的:

#define TOTAL_ELEMENTS 1021

typedef struct UINT1024_tag
{
   UINT8 字节[128];
} UINT1024;

typedef struct flags_tag
{
   UINT1024:TOTAL_ELEMENTS;
} flags_t;

当我尝试编译它时,我收到错误消息,“错误:位域 `<anonymous>' has invalid type”

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

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

4

4 回答 4

8

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

于 2009-10-19T20:31:38.387 回答
3

在标准 C 语言中,位域只能用一组受限制的类型来定义。在 C89/90 中,这些类型仅限于int,signed intunsigned int(一个鲜为人知的细节是,在这种情况下int不保证等同于signed int)。在 C99 中,类型_Bool被添加到支持的集合中。任何其他类型都不能用于位域声明。

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

于 2009-10-19T20:43:45.190 回答
1

采用

 UINT128 blaha;

您没有定义位域。

我不确定您是否了解位域是什么。我的位域是一些位。不是结构数组或类似数组。您到底期望您的代码应该做什么?

编辑:哦,我现在明白了。不,您不能使用自己的类型,只能使用整数。

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

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));
}
于 2009-10-19T20:30:22.383 回答
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));
}

希望我没有搞砸位操作...

于 2009-10-19T21:20:00.287 回答