Structure Padding In C

Suppose we create a user-defined structure. When we create an object of this structure, then the contiguous memory will be allocated to the structure members.

Example

struct student
{
   char a;
   char b;
   int c;
} stud1;

In the previously illustrated example, a structure of student type has been established. An object of this structure has been defined as 'stud1'. Upon object instantiation, a consecutive chunk of memory is assigned to its structure components. Initially, memory allocation is made for the 'a' variable, followed by the 'b' variable, and subsequently the 'c' variable.

What is the size of the struct student?

Now, we determine the dimensions of the struct student. It is assumed that an integer occupies 4 bytes, while a character occupies 1 byte.

Example

struct student
{
  char a; // 1 byte
  char b; // 1 byte
  int c; // 4 bytes 
}

In the scenario mentioned, upon evaluating the size of the struct student, it appears to be 6 bytes. However, this determination is inaccurate. Let's delve into the reasons behind this discrepancy. It is essential to grasp the concept of structure padding to comprehend this discrepancy thoroughly.

Structure Padding

The CPU does not interpret 1 byte sequentially. Instead, it processes data in 1 word chunks.

What does the 1 word mean?

If a 32-bit processor is in use, then it processes data in 4-byte chunks, making 1 word equivalent to 4 bytes.

Example

1 word = 4 bytes

If a 64-bit processor is in use, it processes data in 8-byte chunks, making 1 word equivalent to 8 bytes.

Example

1 word = 8 bytes

Hence, it can be stated that a 32-bit processor can retrieve 4 bytes simultaneously, while a 64-bit processor can retrieve 8 bytes at a stretch. The word size is determined by the specific architecture in use.

Why structure padding?

Example

struct student
{
  char a; // 1 byte
  char b; // 1 byte
  int c; // 4 bytes 
}

If a 32-bit processor (processing 4 bytes at once) is used, the visual depiction of the memory for the aforementioned structure would appear as follows:

As it has been explained that structure encompasses a continuous section of memory, illustrated in the diagram above, with 1 byte allocated for char a, another 1 byte for char b, and 4 bytes for int c, what issue arises in this scenario.

What's the problem?

The 4-byte segments can be retrieved simultaneously due to the 32-bit system architecture. An issue arises when attempting to access variables of different sizes within one CPU cycle. While char a and char b can be accessed in a single cycle, accessing int c requires two CPU cycles. During the initial cycle, the first two bytes are fetched, followed by the retrieval of the remaining two bytes in the subsequent cycle.

If there is no need to access the variables 'a' and 'b' and only 'c' needs to be accessed, it necessitates two cycles. Despite 'c' being 4 bytes and accessible in a single cycle, in this case, it is taking 2 cycles, leading to inefficient CPU cycle utilization. To address this issue, the concept of structure padding was introduced to optimize CPU cycle consumption. Compiler automatically handles structure padding to enhance performance. Let's delve into the process of how structure padding is implemented.

How is structure padding done?

To achieve the padding structure, a blank space is introduced on the left side, as illustrated in the diagram above, and the two bytes that were originally occupied by the 'c' variable are shifted to the right. Consequently, all four bytes of the 'c' variable now reside on the right side. This arrangement enables direct access to the 'c' variable within a single CPU cycle. Post padding, the total memory allocated for the structure amounts to 8 bytes (1 byte + 1 byte + 2 bytes + 4 bytes), which exceeds the previous allocation. Despite the inefficiency in memory usage, the benefit lies in the ability to access the variable swiftly in just one cycle.

Let's create a simple program of structures.

Example

#include <stdio.h>
struct student
{
   char a;
   char b;
   int c;
};
int main()
{
   struct student stud1; // variable declaration of the student type..
   // Displaying the size of the structure student.
   printf("The size of the student structure is %d", sizeof(stud1));
   return 0;
}

In the provided code snippet, a structure named 'student' has been defined. Within the main function, a variable of type student, referred to as stud1, is instantiated. Subsequently, the size of the student structure is determined using the sizeof operator. The resulting size is 8 bytes, influenced by the principles of structure padding that were previously elaborated on.

Output

Output

[Program Output]

Changing order of the variables

Now, let's explore the impact of altering the variable order on the program's output. We will analyze the same program to determine if any changes occur.

Example

#include <stdio.h>
struct student
{
   char a;
   int b;
  char c;
};
int main()
{
   struct student stud1; // variable declaration of the student type..
   // Displaying the size of the structure student.
   printf("The size of the student structure is %d", sizeof(stud1));
   return 0;
}

The code above closely resembles the code from before; the sole modification is the rearrangement of the variables within the student structure. This alteration in order results in a distinct output for each scenario. In the previous instance, the output size was 8 bytes, whereas in this scenario, it amounts to 12 bytes, as evident in the screenshot below.

Output

Output

[Program Output]

Now, we need to understand " why the output is different in this case ".

  • First, memory is allocated to the char a variable, i.e., 1 byte.
  • Now, the memory will be allocated to the int b Since the int variable occupies 4 bytes, but on the left, only 3 bytes are available. The empty row will be created on these 3 bytes, and the int variable would occupy the other 4 bytes so that the integer variable can be accessed in a single CPU cycle.
  • Now, the memory will be given to the char c At a time, CPU can access 1 word, which is equal to 4 bytes, so CPU will use 4 bytes to access a 'c' variable. Therefore, the total memory required is 12 bytes (4 bytes +4 bytes +4 bytes), i.e., 4 bytes required to access char a variable, 4 bytes required to access int b variable, and other 4 bytes required to access a single character of ' c ' variable.
  • How to avoid the structure padding in C?

The automatic process of structural padding is an inherent feature managed by the compiler. Occasionally, there is a need to prevent structural padding in C to ensure that the size of the structure does not exceed the combined size of its individual members.

We have two methods to prevent structure padding in C:

  • One approach is to employ the #pragma pack(1) directive.
  • Another method involves using attributes.

Using #pragma pack(1) directive

Example

#include <stdio.h>
#pragma pack(1)
struct base
{
    int a;
    char b;
    double c;
};
int main()
{
  struct base var; // variable declaration of type base
  // Displaying the size of the structure base
  printf("The size of the var is : %d", sizeof(var));
return 0;
}

By employing the #pragma pack(1) directive in the code snippet above, we prevent structure padding. Omitting this directive would result in a program output of 16 bytes. However, the individual structure members actually occupy a total of 13 bytes, leaving 3 bytes unused. To prevent memory wastage, we utilize the #pragma pack(1) directive to enforce 1-byte alignment for the structure.

Output

Output

[Program Output]
  • By using attribute
  • Example
    
    #include <stdio.h>
    
    struct base
    {
        int a;
        char b;
        double c;
    }__attribute__((packed));  ;
    int main()
    {
      struct base var; // variable declaration of type base
      // Displaying the size of the structure base
      printf("The size of the var is : %d", sizeof(var));
    
        return 0;
    }
    

Output

Input Required

This code uses input(). Please provide values below: