• C Programming Video Tutorials

Structure Padding and Packing in C



In C programming, the concepts of "structure padding" and "structure packing" are interrelated.

Structure Padding is the process that is handled by the CPU architecture. Structure Padding adds a certain number of empty bytes within a structure so that the data members are naturally aligned in memory. The alignment requirements are determined by the processor architecture rather than the language itself. Naturally, the alignment requirements change as per the data bus size or other architectural considerations of a certain CPU architecture.

Structure packing, on the other hand, is a mechanism for minimizing the effect of padding, thereby trying and reduce wasted memory space. We can use certain pragma directives and attributes to achieve packing.

Structure Padding

Let us define a struct type as follows −

struct struct1 {
   char x;
   int y;
   char z;
};

Example 1

Let us check the size in bytes required for a variable of this type −

#include <stdio.h>

struct struct1{
   char a;
   char b;
   int c;
};

int main(){

   printf("Size: %d", sizeof(struct struct1));  
   return 0;
}

Output

When you run this code, it will produce the following output −

Size: 8

The result is contrary to the expectation.

Considering that a char type needs 1 byte, and an int type needs 4 bytes, one might assume the output should be "1 + 1 + 4 = 6 bytes".

Structure Padding

However, the CPU architecture necessitates altering this structure. Considering that we are using a CPU with 32-bit processor, it reads 4 bytes at a time, which means that 1 word is equal to 4 bytes.

In one CPU cycle, it accesses the char "a", then char "b" and the first two bytes of int "c". In the second cycle, the other two bytes are accessed.

Even if we want to read only "c", two CPU cycles are required. For this purpose, the CPU adds two empty bytes before the bytes in which the value of "c" is stored. This mechanism is called as padding.

Structure Padding

This now explains the result we obtained above, that of the size of the struct type to be 8 bytes.

Example 2

Let us change the sequence of members in the above struct type, and set the type of "b" and the type of "c".

#include <stdio.h>

struct struct1{
   char a;
   int b;
   char c;
};

int main(){

   printf("size: %d", sizeof(struct struct1));
   return 0;
}

Output

Run the code and check its output −

size: 12

Out of the 4 bytes in the first word, the first one is allocated to char "a" followed by three empty bytes.

The next 4 bytes that form the next word are used to store int "b". Subsequently, out of the next group of 4, only one is utilized for "c". However, the struct size is 12.

Structure Packing

The padding, forced by the CPU architecture is unavoidable, however there are ways to minimize padding. It can be done with the use of −

  • Using #pragma pack(1) directive
  • Using packed attribute

Using #pragma pack(1) Directive

The #pragma pack(1) preprocessor directive forces the compiler to disregard the padding, and align the structure members end to end during the memory allocation process.

Example

Let's add this directive at the top of the code used previously, and see the result −

#include <stdio.h>
#pragma pack(1)

struct struct1{
   char a;
   int b;
   char c;
};

int main(){

   printf("size: %d", sizeof(struct struct1));
   return 0;
}
Output

Run the code and check its output −

size: 6

We can see the structure padding has been avoided and reduced memory wastage.

Using __attribute__((packed))

With GCC, we can use attributes to specify various special properties of structure and union types. The attributes are: aligned, deprecated, packed, transparent_union, unused, and visibility. The syntax of applying these attributes is "__attribute__ ((...))".

Example

Here, we are going to use packed attribute in the definition of our struct type.

#include <stdio.h>

struct __attribute__((packed)) struct1{
   char a;
   int b;
   char c;
};

int main(){

   printf("size: %d", sizeof(struct struct1));
   return 0;
}
Output

Run the code and check its output −

size: 6

This method also avoids the effect of padding.

Advertisements