Structure Padding

consider the following 12 byte structure :
 
typedef struct {
int x;
short x2;
int y;
short y2;
} msgStruct;

After compilation it will be a 14 byte structure!
Why ? ->Alignment!
 

Remember the following rules:
  • data structures are maximally aligned, according to the size of the largest native integer
  • other multibyte fields are aligned to their size, e.g., a four-byte integer’s address will be divisible by four



                           

             after padding
                                               

 



This can be avoided :

1. include padding to data structure

typedef struct {
int x;
short x2;
char pad[2];
int y;
short y2;
} msgStruct;


2. reorder fields

typedef struct {
int x;
int y;
short x2;
short y2;
} msgStruct;



1. What will be the output for below C programme in gcc compiler ?
size of structure s1 and s2 is same or different ?

#include <stdio.h>
struct s1{
        int i;
        int j;
        char a;
        char b;
};
struct s2{
        int i;
        char a;
        int j;
        char b;
};
void main()
{
        printf("size of struct s1 is : %d\n", sizeof(struct s1));
        printf("size of struct s2 is : %d\n", sizeof(struct s2));
}

Output :
size of struct s1 is : 12
size of struct s2 is : 16

Explanation :  
There are 4 members declared for structure in above program. In 32 bit compiler, 4 bytes of memory is occupied by int datatype. 1 byte of memory is occupied by char datatype.
Hence Output of  both should be same as 16.

Memory Allocation in Structure : Always, contiguous(adjacent) memory locations are used to store structure members in memory.

Memory Allocation for Structure S1 (4 + 4 + 4).
                            |------------|------------|-------------|
                            |          i         |         j          |  a | b  |   |   |
                            |------------|------------|-------------|

                                   4 Bytes         4 Bytes       4 Bytes

 Memory Allocation for Structure S2 : (4 + 4 +4 + 4)
                            |------------|------------|------------|------------|
                            |          i         |  a |    |   |   |         j         |  b |    |   |   |
                            |------------|------------|------------|------------|

                                   4 Bytes         4 Bytes       4 Bytes         4 Bytes



Architecture of a computer processor is such a way that it can read 1 word (4 byte in 32 bit processor) from memory at a time. To make use of this advantage of processor, data are always aligned as 4 bytes package which leads to insert empty addresses between other member’s address.

How to avoid structure padding in C ?
#pragma pack ( 1 ) directive can be used for arranging memory for structure members very next to the end of other structure members. The default compiler alignment is of 4 bytes. We need to change it to 1 byte. For that, do the following steps:
  • Push the current compiler alignment into the stack.
  • Set the alignment into 1 byte.
  • Declare the structure.
  • Restore the default compiler alignment from the stack.
Please check the below program where there will be no addresses (bytes) left empty because of structure padding.

#include <stdio.h>
#pragma pack(1)
struct s1{
        int i;
        int j;
        char a;
        char b;
};
struct s2{
        int i;
        char a;
        int j;
        char b;
};
void main()
{
        printf("size of struct s1 is : %d\n", sizeof(struct s1));
        printf("size of struct s2 is : %d\n", sizeof(struct s2));
}
 
Output :
size of struct s1 is : 10
size of struct s2 is : 1
0

Optimization of Space in Structure using Bit Fields :
 #include <stdio.h>

// A space optimized representation of date
struct date
{
   // d has value between 1 and 31, so 5 bits
   // are sufficient
   unsigned int d: 5;

   // m has value between 1 and 12, so 4 bits
   // are sufficient
   unsigned int m: 4;

   unsigned int y;
};

int main()
{
   printf("Size of date is %d bytes\n", sizeof(struct date));
   struct date dt = {31, 12, 2014};
   printf("Date is %d/%d/%d\n", dt.d, dt.m, dt.y);
   return 0;
}

Output : 
Size of date is 8 bytes
Date is 31/12/2014
 

Some interesting facts about bit fields in C.
A special unnamed bit field of size 0 is used to force alignment on next boundary. For example consider the following program. 

#include <stdio.h>
// A structure without forced alignment
struct struct1
{
   unsigned int x: 6;
   unsigned int y: 8;
};

// A structure with forced alignment

struct struct2
{
   unsigned int x: 6;
   unsigned int: 0;
   unsigned int y: 8;
};
int main()
{
   printf("Size of struct1 is %d bytes\n", sizeof(struct struct1));
   printf("Size of struct2 is %d bytes\n", sizeof(struct struct2));
   return 0;
}
 
Output:

Size of struct1 is 4 bytes
Size of struct2 is 8 bytes


No comments:

Post a Comment