Bitfields in a structure are weird, as I covered in last week’s Lesson. If you’re a nerd who appreciates bits and bit manipulation, you’re probably in love. These bitwise tricks are things the C language excels at. With a keen knowledge of bits, and a desire to use integer values beyond the standard widths, a nerd can have a lot of fun in C.
One of the more unusual bitfield constructions I’ve seen appears in the C standard documentation. It looks like this:
struct {
char a;
int b:5, c:11,:0, d:8;
struct { int ee:8; } e;
}
Above you see a structure with a char member a
, plus a bitfield with three variables, b
, c
, and d
. The third member is a nested structure with a single 8-bit bitfield. I want to focus on middle line:
int b:5, c:11,:0, d:8;
Integer member c
is set to a width of 11 bits, then you see a comma and :0
. This curious item isn’t a member of the structure, nor is it somehow attached to variable c
. The :0
item is used for alignment.
All data stored in memory is aligned, either at 32-bit or 64-bit intervals depending on system architecture. This alignment doesn’t mean that each character in a string occupies a 32-bit (four byte) chunk of memory. No, but that string itself starts at a 32-bit boundary.
What the :0
item does in a structure is to align the bitfield value that follows it with the next memory boundary.
To demonstrate, I concocted the following code:
2021_11_13-Lesson.c
#include <stdio.h> int main() { struct bitfield { unsigned a:1, b:7; }; struct bitfield align; align.a = 1; align.b = 15; printf("size of align = %lu\n",sizeof(align)); printf("align.c = %u\n",align.a); printf("align.d = %u\n",align.b); return(0); }
The bitfield
structure contains two unsigned members, a
and b
. The first is a single bit, the second consists of a bitfield of 7 bits.
Values are assigned at Lines 10 and 11. At Line 12, the size of the align
structure is output. Then the structure’s member values are output:
size of align = 4
align.c = 1
align.d = 15
The align
structure occupies four bytes of storage, 32 bits.
You can’t see it, but for efficiency’s sake, both members align.c
and align.d
are stored in the same byte. If I add a :0
to the structure definition, alignment is forced:
unsigned a:1, :0, b:7;
The above modification to Line 6 adds the :0
alignment item to the definition. Now both values are stored in different 32-bit chunks of memory; member b
is aligned. Here is the updated output:
size of align = 8
align.c = 1
align.d = 15
Due to the :0
thingie, the align
structure now occupies 64-bits of memory, two 32-bit chunks for eight bytes. Member a
is stored in one chunk and member b
in the other. The bit values aren’t shared in a single byte. This effect is what you get when a :0
is specified in the structure’s definition.
Bit fields are designed to save memory. Because memory is abundant in today’s systems, seeing bitfields used in a structure is rare. Even rarer is the need to align the bitfields, though if the need arises you now know the secret.