views:

83

answers:

3

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?

+6  A: 

The first example won't work because you can only declare bitfields inside structs. This is syntax, not semantics, as you said, but there it is. If you want a bitfield, use a struct.

JSBangs
Joe
@Joe: There are minimum defined sizes for the types - for the unsigned types, it is 8 value bits for `unsigned char`, 16 value bits for `unsigned short` and `unsigned int`, 32 value bits for `unsigned long` and 64 value bits for `unsigned long long`.
caf
+3  A: 

Why would you want to do such a thing? A bit field of 12 would on all common architectures be padded to at least 16 or 32 bits.

If you want to ensure the width of an integer variable use the types in inttypes.h, e.g int16_t or int32_t.

Jens Gustedt
Very good point. I will take your advice in this case. But the question still stands in abstract. And the numbers given in the text were arbitrary.
Joe
@Joe: "But the question still stands in abstract". Answer: there's no need to do such a thing!
Oli Charlesworth
@Joe: the only reasonable numbers on modern architectures are 8, 16, 32 and 64 for such a thing.
Jens Gustedt
@Joe: alignment requirements make what you want to do difficult for a compiler to support. In practice your fields would be aligned to the nearest native word size, so it really doesn't buy you anything over using `int` or `long` or `short`. Bitfields are useful within the context of a struct (such as mapping the bits in a processor status word), not so much outside of it. Like Jens says, if you need words of specific sizes, use the types in `inttypes.h`.
John Bode
@Jens: there are still some oddball architectures out there where the word size isn't a multiple of the byte size (e.g., 8-bit bytes, 36-bit words), so I could see wanting something like a 9-bit field.
John Bode
I don't want to copy-paste a comment, but see my comment on JSBangs' answer for the reason behind asking the question.
Joe
+2  A: 

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.

Gilles
C99 also adds `unsigned long long` with at least 64 bits. In most cases, these (the plain types) are all you need.
caf