Memory alignment in structure

Posted by Bartosz Stempień on August 28, 2019 · 5 mins read

Hello,
today we discuss topic, which many of you don’t know.
This is more interesting fact than useful knowledge unless you work with packets.

Reading below code:

#include <iostream>
int main()
{
    struct A
    {
        int a;
        char b[3];
        long c;
        char d;
    };
    struct B
    {
        long c;
        int a;
        char b[3];
        char d;
    };
    std::cout << "The size of A is " << sizeof(A) << std::endl;
    std::cout << "The size of B is " << sizeof(B) << std::endl;
    
    return EXIT_SUCCESS;
}

it is obvious that those two structs have the same size. But this is not the truth.
Size A is 24 bytes, size B is 16 bytes, word size = 1 byte.
Why? And what is word in this case?

First of all we have to clear the definitions:
· Data alignment - data is being put in the memory of the computer at space that equals a multiple of the word size.
· Data structure padding - to align the data sometimes compiler can add extra bites to make memory continuous.
· Word - the amount of data that a machine can process at one time. Word size could be 4 bits or 64 bits. It is up to processor.

Word size: 1 byte

This is struct A in the memory:
Structure A
As you can see in the picture above the compiler add some padding.

When we take struct B we get: Structure B

Padding bytes are uninitialized, which means that they hold any values previously written to the stack (C11: sometimes they can be initialized).
You can prevent it setting all bytes to zero:

memset(&YOUR_STRUCTURE, 0, sizeof(YOUR_STRUCTURE));

Some processors even require data alignment, for example ARM processor could crash if you try to access unaligned data. Modern CPUs in laptops/PC are less sensitive to such requirements.
Based on this LINK: there is no measurable difference between unaligned and aligned data.

Should we take care of extra memory and change our structures even if they have 100 lines?
No, because a compiler can add extra informations to the memory block of size to get sometimes better performance and we avoid problem with some CPUs.

But what about network packets?
We send extra useless informations, packets are bigger, how to change the very big structure in easy way?
There is a simple solution (or maybe two to be more precise):

#pragma pack(1)

or

__attribute__ ((packed))

It depends of compiler you have. If you use gcc the second option will be the good one. This works the same way as pragma but it is only available on gcc compiler.

You can get the size of the word using this code:

#include <iostream>
int main()
{
    std::cout << sizeof(size_t) << std::endl; // 32 bits machine - 4 bytes 
                                              // 64 bits machine - 8 bytes
    return EXIT_SUCCESS;
}

Assuming all the informations:
You care about memory alignment only if you deal with the Internet packets and other stuffs like that :)
In other case it doesn’t matter, let your compiler do his job.

Thanks for your attention. I hope you enjoy the post :)