Packing and Padding in C

Packing and Padding in C

If you are a software developer, there is a high chance that you were taught C Language as one of the first basic languages to learn to code. Now if you have done some coding in C, you might have also come across something called ‘Structures’.
But what is a Structure & why should I use it?

Well, everyone has their limits & so does Arrays, as they are only good for storing similar type of data. Let’s suppose you want to store 5 different types of data altogether. Here’s where Structures come to the rescue. Let's quickly take a small example:

struct student{
int roll_number;
char name[10];
float height;
};

Here, our structure ‘student’ contains 3 different datatypes but it could be many more as per the user’s requirement.

Time for a quick question: Can you guess the size of our structure?

Well, take a guess, go on, and take your time.

The size of different data types depends on the type of processor you have. As per modern 32/64 bit processors, the size of int is 4 Bytes, Char is 1 Byte & Float is 4 Bytes.

Structure Padding in C

Let’s calculate the size of our student structure : 4B + (1B x 10) + 4B = 18 Bytes

Well, wrong! There exists this thing called “Structure Padding” which pads the memory if it’s not aligned as per the datatype’s need due to which the actual size of our structure would be: 4B + (1B x 10) + 2B (padding) + 4B = 20 Bytes

Structure Padding in C

Since float & int have their size as 4Bytes, also means that in the memory they’ll be stored in a 4-byte aligned fashion i.e. at memory addresses which are in multiples of 4. So, in our case, the starting 4Bytes are taken by the integer variable, next 10Bytes by the character variables but since the memory but 2 memory cells will be left empty due to padding and the memory which is allocated to float will be from the next address which is divisible by 4 i.e. from 116.

Packing in C

In small systems with memory crunch, this way of memory allocation may end up wasting a lot of space. To overcome this problem, there exists something called 'Packing'. It does exactly what you might be thinking, it instructs the compiler to not waste any memory space and start the memory allocation to the variables from the next available memory space immediately irrespective of their byte alignment.

//name aliasing for better readability: typedef oldname aliasName
typedef __attribute__((__packed__)) packed 

struct packed student
{
    int roll_number;
    char name[10];
    float height;
};

Here, we have packed our structure and it would look something like this:

The size of this structure would be: 4B + (1B x 10) + 4B = 18 Bytes. Notice how the two memory cells previously left empty have been occupied by the float variable. This way, we did not waste any extra space & can utilise our systems to their fullest.

The argument that made the case for such structure padding is that the code will work without SEGV on machines that have hardware alignment restrictions i.e. requiring 32-bit integers to be on 32-bit boundaries.

There used to be a lot more of these, but they are going away both by attrition and clever silicon that lets them do unaligned accesses efficiently.

Well, that's a wrap! That's it for this blog post. I hope you found this memory allocation insight interesting! If you have any questions or comments, please leave a reply or contact me on Twitter. Thank you!