Alignment

Before going into details of struct packing and padding in c let us discuss alignment. Data alignment is related to the memory location where it is stored in memory. each data type in c/c++ has alignment requirement. A variable is naturally aligned if it exists at a memory address that is a multiple of its size. so chars can start on any byte address, but 2-byte shorts must start on an even address, 4-byte ints or floats must start on an address divisible by 4, and 8-byte longs or doubles must start on an address divisible by 8.

The data alignment is important for efficient execution of a program,as modern processor access memory in “word” size. The word size depends upon the processor register size.The word size  of a processor is defined as the largest natural size for arithmetic which is generally the size of the registers in the machine. so 32 bit system has word size of 4 byte and 64 system has word size of 8 byte.

processors access the data in register by their word size at a time.hence proper alignment of data in a program gives good execution speed and stability. unaligned memory access is slower on architectures that allow it (like x86 and amd64), and is explicitly prohibited on strict alignment architectures like SPARC.During compilation of c/c++ program compiler introduces a padding data for natural alignment of data member of struct and union. let us consider below example for understanding “struct, union packing and padding in c/c++”.

Ex.

#include<stdio.h>
struct DataNode
{
  int a;
  char b;
  int c;
};
struct DataNode2
{
  char a;
  char b;
  int c;
};
struct DataNode mynode;
struct DataNode2 mynode2;
int
main ()
{
  printf ("size of DataNode strpcture is %ld", sizeof (mynode));
  printf ("\n   Address of a    = %p", &mynode.a);
  printf ("\n   Address of b    = %p", &mynode.b);
  printf ("\n   Address of c    = %p", &mynode.c);
  printf ("\n");
  printf ("size of DataNode2 strpcture is %ld", sizeof (mynode2));
  printf ("\n   Address of a    = %p", &mynode2.a);
  printf ("\n   Address of b    = %p", &mynode2.b);
  printf ("\n   Address of c    = %p", &mynode2.c);
  printf ("\n");
  return 0;
}

 

:::::::::::::::::output of above program::::::::::::::::::::::::::::::::::::::::::::::::

 Address of a    = 0x601054
   Address of b    = 0x601058
   Address of c    = 0x60105c
size of DataNode2 strpcture is 8
   Address of a    = 0x60104c
   Address of b    = 0x60104d
   Address of c    = 0x601050

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

struct packing and padding in c

PADDING

Padding aligns structure members to “natural” address boundaries: and this is done by compiler during program compilation. compiler insert extra zero bytes for the struct data members for their natural alignment.

#include<stdio.h>

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

struct test_t test = { 10, 20, 30 };

int main() {
	return 0;
}

And compiled it with the -S option

$gcc -c test.c -S -o test.s

The file test.s –

	.file	"test.c"
.globl test
	.data
	.p2align 2
	.type	test,@object
	.size	test,12
test:
	.long	10
	.byte	20
	.zero	3
	.long	30
	.ident	"GCC: (GNU) 3.2.2 [FreeBSD] 20030205 (release)"

Notice the emphasized code. You can see that the structure “test” is being declared. First the field “a” (int) as .long 10 followed by “b” (char) as .byte 20. To keep the fields’ word alignment, notice that GCC has added 3 zero bytes (.zero 3) before field “c” (int) which is declared as .long 30. This makes the effective sizeof struct test_t as 12 instead of the expected 9.

PACKING

Packing, prevents compiler for padding – it has to be explicitly requested – under GCC compiler through  __attribute__((__packed__)), so the following code

struct __attribute__((__packed__))ABC {

char a;
int b;
char c;
};

would produce structure of size 6 on a 32-bit architecture. and without __attribute__((__packed__)) this size would be 12 on 32-bit architecture.

GCC allows you to specify attributes of variables and structures using the keyword__attribute__, the syntax of which is __attribute__((attribute list)). One such attribute is __packed__ which specifies that

a variable or structure field should have the smallest possible alignment–one byte for a variable, and one bit for a field, unless you specify a larger value with the aligned attribute.
GCC Manual

which means that GCC will not add any of the zero’s for padding (for memory alignment).

#include<stdio.h>
struct __attribute__((__packed__)) ABC {
	char a;
	int b;
	char c;
};
struct XYZ {
	char a;
	int b;
	char c;
};
struct ABC abc;
struct XYZ xyz;
int main() {
	printf("size of struct ABC is %ld\n", sizeof(abc));
	printf("size of struct XYZ is %ld\n", sizeof(xyz));
	return 0;
}

 

:::::::::::::::::output::::::

size of struct ABC is 6
size of struct XYZ is 12



Related Contents to follow