Search code examples
csyntaxstackbit-fields

Why can't I declare bitfields as automatic variables?


I want to declare a bitfield with the size specified using the a colon (I can't remember what the syntax is called). I want to write this:

void myFunction() 
{   
  unsigned int thing : 12;
  ...
}

But GCC says it's a syntax error (it thinks I'm trying to write a nested function). I have no problem doing this though:

struct thingStruct
{
  unsigned int thing : 4;
};

and then putting one such struct on the stack

void myFunction() 
{   
  struct thingStruct thing;
  ...
}

This leads me to believe that it's being prevented by syntax, not semantic issues.

So why won't the first example work? What am I missing?


Solution

  • As others have said, bitfields must be declared inside a struct (or union, but that's not really useful). Why? Here are two reasons.

    • Mainly, it's to make the compiler writer's job easier. Bitfields tend to require more machine instructions to extract the bits from the bytes. Only fields can be bitfields, and not variables or other objects, so the compiler writer doesn't have to worry about them if there is no . or -> operator involved.

    • But, you say, sometimes the language designers make the compiler writer's job harder in order to make the programmer's life easier. Well, there is not a lot of demand from programmers for bitfields outside structs. The reason is that programmers pretty much only bother with bitfields when they're going to cram several small integers inside a single data structure. Otherwise, they'd use a plain integral type.

    Other languages have integer range types, e.g., you can specify that a variable ranges from 17 to 42. There isn't much call for this in C because C never requires that an implementation check for overflow. So C programmers just choose a type that's capable of representing the desired range; it's their job to check bounds anyway.

    C89 (i.e., the version of the C language that you can find just about everywhere) offers a limited selection of types that have at least n bits. There's unsigned char for 8 bits, unsigned short for 16 bits and unsigned long for 32 bits (plus signed variants). C99 offers a wider selection of types called uint_least8_t, uint_least16_t, uint_least32_t and uint_least64_t. These types are guaranteed to be the smallest types with at least that many value bits. An implementation can provide types for other number of bits, such as uint_least12_t, but most don't. These types are defined in <stdint.h>, which is available on many C89 implementations even though it's not required by the standard.