Understanding of structure padding in C with alignment

structure padding in C

Many times I have read about the most confusing topic structure padding in C and memory alignment in C. Understanding of memory alignment is very important for a software engineer who works on the memory. Sometimes if we don’t care about memory alignment then it may cause a serious issue.

I have read a lot of articles and blogs to understand memory alignment and structure padding in C. But always I had some confusion and questions regarding the memory alignment and structure padding in C. So finally I had thought to dig the internet to understand the memory alignment and padding.

When I had read about the memory alignment then I found generally people confuse about the bad effect of the alignment, according to some reputed blog, memory alignment affects the performance of the CPU and the processor takes some extra fetch to access the unaligned memory.

So then I had started to solve this mysterious question and I found that alignment is only the micro-optimization techniques, the current processor is too smart and they know how to handle the unaligned memory but in some bad situation, the processor takes some extra cycles to fetch the unaligned memory. So it’s good for the programmer to care about the alignment when he writes the program.

In real-world processor, does not read or write the memory byte by byte but actually, for performance reason, it accesses the memory in the formats like 2,4,8,16 and 32 bytes of chunks at a time.

In 32 bits processor word size is 4 bytes if the data address within the 32 bits then it perfectly fit in the memory alignment but if it crosses the boundary of 32 bits then the processor has to take some extra cycles to fetch the data from that unaligned memory.

structure padding in C
Image describes the aligned memory data for 32 bits system.

 

 

When memory is aligned then the processor easily fetches the data from the memory. In images 1 and 2, you can see that the processor takes one cycle to Access the aligned data.

Memory Alignment

 

When memory is not aligned then the processor takes some extra ticks to access the unaligned memory, in the below image we access a 4-byte data from the unaligned address which looks like as below image.

Memory not alligned

 

The below image describes the steps, and how is the processor access the unaligned memory

When the processor gets an unaligned memory then it takes the following steps to access the unaligned memory.

  1. CPU selects the unaligned memory which represents through the black dark border.
  2. CPU access the whole 4 bytes above and below the black square border.
  3. Shift one byte above and three bytes below in corresponding to the above and below chunks of memory.
  4. Combined both chunks of data and get the actual bytes of data.
Steps taken by processor to access unaligned memory
Image describes how to processor access the unaligned memory.

The RISC processor throws the exception when he faced the unaligned memory but some MIPS have some special instruction to handle the unaligned memory situation, unaligned memory is not a big issue for the Intel x86 processor it easily handles the unaligned memory but sometimes it takes some extra ticks to fetch the unaligned memory.

In the program, there are mainly two-property attached to the variable first is the value of the variable, and the second is its address. In the case of the Intel X86 architecture address of the variable in the multiple of 1, 2, 4, or 8, in other words, we can say that the address of the variable should be multiple of the power of 2.

Generally, the compiler handles the scenario of alignment and it aligned the variable in their boundary. You don’t need to worry about the alignment, in the 32 bits X86 architecture alignment of data types is generally similar to their length.

 

In below table, I have described the alignment of some primitive data types which frequently used in the program

Data Type 32-bit (bytes) 64-bit (bytes)
char 1 1
short 2 2
int 4 4
float 4 4
double 8 8
pointer 4 8

Note: Alignment of data types mandated by the processor architecture, not by language.

 

A final thought about structure padding in C:

When you create an object of structure or union the compiler may insert some extra bytes between the members of the structure or union for the alignment. These extra unused bytes are called padding bytes and this technique is called structure padding in C.

The C standard does not define the value of these padding bytes which means the value of the padding bytes is unspecified. It is the reason we must not compare the structure using the memcmp().

Padding increases the performance of the processor at the penalty of memory. In structure or union data members are aligned as per the size of the highest bytes member to prevent the penalty of performance.

 

If you want to learn more about the c language, here 10 Free days C video course for you.

Your free trial is waiting

 

Here, I have described some examples to clarify the concept of structure padding in C:

Example 1:
typedef struct
{
    char A;
    int B;
    char C;
} InfoData;

 

Memory layout of structure InfoData

Memory Layout

In the above structure, an integer is the largest byte size member. So to prevent the penalty compiler inserts some extra padding bytes to improve the performance of the CPU. So the size of the InfoData will be 12 bytes due to the padding bytes inserted by the compiler for the data alignment.

Note: In the case of structure and union we can save the wastage of memory to rearrange the structure members in the order of largest size to smallest.

Example 2:
typedef struct
{
    int A;
    char B;
    char C;
} Element;

 

Memory layout of Element after the rearranging of his members

Memory Layout

 

In the above example, the size of the InfoData is 8 bytes due to 2 tail padding bytes inserted by the compiler for the data alignment.

Example 3:
typedef struct
{
    double A; // 8-byte
    char B; // 1-byte
    char C;   // 1-byte

} InfoData;

 

Memory layout of structure InfoData

structure padding in C

 

The largest size member is double (8 bytes), hence compiler aligned the memory in the form of 8 bytes. So here compiler adds 6 padding bytes for the alignment, and the size of the InfoData will be 16 bytes.

 

How to avoid Structure Padding in C?

If you want you can avoid the structure padding in C using the pragma pack (#pragma pack(1) ) or attribute ( __attribute__((__packed__)) ). Let us see an example code,

#include <stdio.h>

#pragma pack(push, 1)
typedef struct
{
    double A; // 8-byte
    char B; // 1-byte
} InfoData;
#pragma pack(pop)

/* main function */
int main(int argc, char *argv[])
{
    printf("\n Size of Structure = %d\n\n\n\n",sizeof(InfoData));

    return 0;
}

Output: 9

 

Note: We can also change the alignment of structure, union, or class using the “pack” pragma directive, but sometimes it becomes a crucial reason for the compatibility issues in your program. So it’s better always use the default packing of the compiler.

See the below program which explains how we can change the structure packing  in C using the pragma directive:

Example Code 1:
#include <stdio.h>

// size = 10, alignment = 2-byte, no padding bytes for these struct members

#pragma pack(push, 2)
typedef struct
{
    double A; // 8-byte
    char B; // 1-byte
    char C;   // 1-byte

} InfoData;
#pragma pack(pop)


/* main function */
int main(int argc, char *argv[])
{
    printf("\n Size of Structure = %d\n\n\n\n",sizeof(InfoData));
    
    return 0;
}

Output:

Output
In the above code, I have made the alignment of code is 2 bytes using the pragma pack directive.

 

 

 

 

Example Code 2:
#include <stdio.h>

// size = 12, alignment = 4-byte, required 2 padding bytes for these struct members

#pragma pack(push, 4)
typedef struct
{
    double A; // 8-byte
    char B; // 1-byte
    char C;   // 1-byte

} InfoData;
#pragma pack(pop)


/* main function */
int main(int argc, char *argv[])
{
    printf("\n Size of Structure = %d\n\n\n\n",sizeof(InfoData));

    return 0;
}

 

OutPut:
structure padding concept
In the above code, I have made the alignment of code 4 bytes using the pragma pack directive.
Example Code 3
#include <stdio.h>

//Using the default packing of compiler
typedef struct
{
    double A; // 8-byte
    char B; // 1-byte
    char C;   // 1-byte

} InfoData;


/* main function */
int main(int argc, char *argv[])
{
    printf("\n Size of Structure = %d\n\n\n\n",sizeof(InfoData));
    
    return 0;
}

Output:

structure padding in C

You can see this article, Top 11 structure padding questions

 

Conclusion

Finally, I understand memory alignment increases the performance of the processor and we have to care for the alignment of the memory for the better performance of the program. CPU performs better with aligned data as compared to unaligned data because some processor takes an extra cycle to access the unaligned data. So when we create the structure, union or class then we have to rearrange the member in a careful way for the better performance of the program.

Your opinion matters

Although here I have tried to puts a lot of points regarding the alignment and structure padding. I would like to know your opinion regarding the memory alignment and structure padding, so please don’t forget to write a comment in the comment box.

 

Recommended Posts for you



Reference: structure padding.

15 comments

  1. First, I would say that you need to be aware of alignment and byte padding in structures. But, you should always try to let the compiler and system calls take care of it for you and never try to do it by hand unless absolutely necessary. For instance, you need to know that a call to malloc always returns a pointer to memory that is aligned for all data types. if you want to put multiple things in part of memory you allocate, define a structure for that instead of manually deciding where things will go and calculating offsets – it will in the end come out very badly. Also any shared memory segment you get is always aligned for any data type. Never ever ever send structures over sockets, or write them to files.

    Also, it is not just a matter of speed, if you try to operate on incorrectly aligned double floating point numbers, it might silently give incorrect results, or, even core dump, depending on the processor architecture and OS. The reason for byte padding in structures is so that arrays of structures will all be correctly aligned if the first one is aligned. If you did not have the byte padding to maintain alignment, and you passed a pointer to a floating point in one of the structures in the array, it might not be aligned, and, whatever you did with that pointer is undefined and bad things can happen.

    1. Yes, Don Carr, nowadays all compilers are very smart and they are capable of making memory aligned. I have checked on Keil IDE, malloc also returns a pointer to memory that is aligned for all data types. So if used the malloc in the program then no need to make the allocated memory aligned manually.
      Thanks for pointing here, regarding the unaligned memory. An unaligned memory does not only affect the speed but also sometimes create a bus error and you can face the BSOD( blue screen of death) or any issues depending on the operating system and processor architecture.

  2. Usually compilers deal with the alignment nowadays, which also basically depends on the architectural Bus implementation especially, ARMv6 onwards support unaligned access.
    Old architectures had bus error for both instruction and data fetch, unlike the system programming the padding added by a cross-compiler may not be that straight forward.
    Mostly to grab on the alignment added by the compiler linker map file can also be used to see the impact and padding added by the compiler specially when using a dynamic memory pool.
    Nice tutorial.

  3. If i build the code
    struct book
    {
    double A; // 4-byte
    char B; // 1-byte
    char C; // 1-byte

    };
    struct book b;

    In MPLAB with 16bit complier for 16 bit controller the it return the size of structure as 6 bytes and not 8 bytes. i.e it is not following the largest member in structure rule for padding.

Leave a Reply

Your email address will not be published. Required fields are marked *