user3491702
user3491702

Reputation: 95

size of a struct with bitfields not aligned on byte boundary

This is my program

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main() {
    struct bitfield {
         unsigned a:3;
         char b;
         unsigned c:5;
         int d;
    }bit;

    printf("%lu \n",sizeof(bit));
    return 0;
}

I was expecting size of this structure to be, well quite a lot, but it comes out to be 8 on my machine, because unsigned is 4 bytes. Now reason I was expecting to be more than that was because I would expect char b to be on a byte boundary, so that it is aligned in the memory correctly. Now my guess is that compiler is putting a, b, c, all in those 4 bytes. I am new to C, so please bear with me. Is my assumption that all the other data types besides bit fields have to be necessarily on byte incorrect? If it is correct, I would expect, a to take the whole unsigned int, and b to take a byte and then padding of 3 bytes, and then so on. What am I missing here?

Upvotes: 0

Views: 1397

Answers (2)

Myst
Myst

Reputation: 19221

I don't seem to understand the conflict.

you basically have:

struct bitfield {
     unsigned a:3;
     unsigned padding1:5;
     char b;
     unsigned c:5;
     unsigned padding2:3;
     unsigned padding3:8;
     int d;
}bit;

a is on byte 1 boundary, it uses three bits + 5 bit padding (because there aren't any more bit fields to use up the leftover bits).

b is on byte 2 boundary, it uses a whole byte.

c is on byte 3 boundary, it uses five bits + 3 bit padding (because there aren't any more bit fields to use up the leftover bits).

- int padding comes here -

d is on an int boundary (4 bytes on your machine). It uses 1 byte for padding + 4 bytes for data.

All together, 8 bytes...

... although, as pointed out by @ JonathanLeffler in the comments, this is implementation specific and doesn't mean every compiler will behave the same.

Upvotes: 3

CRoemheld
CRoemheld

Reputation: 949

You usually align the bitfields in that way they share a single byte together. When you place another variable in between bitfields, the unused bits end up using space in memory you don't need but still use space.

I tested your code with some values and ran the program in gdb.

bit.a = 1;
bit.b = 'a';
bit.c = 4;
bit.d = 1337;

When printing the memory in gdb, the output looks like this

(gdb) x/8b &bit
0x7fffffffe118: 00000001    01100001    00000100    00000000
                00111001    00000101    00000000    00000000

So we see that the first byte is completely used from field a, although it only uses 3 bits. The character a in field b also takes up a byte. The third byte (00000100) matches value 4 of field c and here's whats interesting:

You then have an integer which uses 4 bytes (in the gdb output above the last 4 bytes, bottom line), but there's an extra zero byte in there. This is a common pratice for compilers as they try to align the memory in an optimized way.

Upvotes: 2

Related Questions