tags:

views:

368

answers:

4

I would like to define a large bitfield for the purpose of quickly monitoring the status a very large structure of elements. Here is what I have so far:

#define TOTAL_ELEMENTS 1021

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

typedef struct flags_tag
{
   UINT1024:TOTAL_ELEMENTS;
} flags_t;

When I try compiling this, I get the error message, "error: bit-field `<anonymous>' has invalid type"

Can bit-fields only be used on certain types? I thought that if I defined a large-enough variable, the massive bitfield needed for my application could then be defined because the bitfield has to be no larger than the type used to define it.

Any thoughts or suggestions would be appreciated.

+1  A: 

use

 UINT128 blaha;

You're not defining a bitfield.

I'm not sure you understand what a bitfield is. I bitfield is a number of bits. Not an array of structs or similar. What exactly are you expecting that your code should do?

Edit: oh I see now. No, you can't use your own types, just ints.

Try this (untested code):

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));
}
Thomas
Thanks, but indexing into the memory space is not the problem. I was just looking for a "clean" way to declare it and have the compiler do some of the work for me.
Jim Fell
+5  A: 

Bit fields must fit within a single int, you can't use arbitrary sizes. Honestly the ANSI bitfield implementation is kinda broken. It misses a lot of other stuff too, like control over padding and layout that real-world applications usually need. I'd consider writing some macros or accessor functions to abstract the larger sizes and giving up on the bitfield syntax.

Andy Ross
Thanks, Andy. That's kind of what I figured was happening. Basically, my master struct is made up of a number of smaller structs. The using macros is an interesting idea; I'll give it some more thought.
Jim Fell
+1  A: 

In standard C language bit-fields can only be defined with a restricted set of types. In C89/90 these types are limited to int, signed int and unsigned int (a little-known detail is that in this context int is not guaranteed to be equivalent to signed int). In C99 type _Bool was added to the supported set. Any other types cannot be used in bit-field declaration.

In practice, as a popular extension, compilers normally allow any integral type (or also enum type) in bit-field declaration. But a struct type... No, I'm not aware of any compiler that would allow that (let alone that it doesn't seem to make much sense).

AndreyT
A: 

As other have said, the C standard doesn't allow bit-fields to exceed the size of their attached integer type.

I'd suggest using plain arrays with some macro magic:

#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));
}

Hopefully, I didn't mess up the bit ops...

Christoph