Declaring Structures, Trick #3

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.

Leave a Reply