How to Use struct Alignment and Padding in C
- Understand the Basics of Alignment and Padding in C
- Use Member Reordering Technique to Save Space in Objects in C
This article will explain several methods of how to use struct
alignment and padding in C.
Understand the Basics of Alignment and Padding in C
All objects in memory are represented as the primary data types like: char
, short
, int
, long
, pointer
etc. These data types have their corresponding size in memory. On most contemporary 64-bit desktop processors, the sizes are 1 byte for a char
, 2 bytes for a short
, 4 bytes for an int
, 8 bytes for a pointer
, and so on. Note that these are not guaranteed sizes (except for char
), but one can retrieve the object’s size using the sizeof
operator. Now, alignment is the method that compilers employ to place variables in the memory, implying that each basic data type is stored at the address divisible by the corresponding size.
Usually, alignment is utilized to access data objects faster and efficiently. Alignment forces continuously declared different data types to include some spacing between their addresses. Namely, if we declare a structure st1
with one pointer and a char
as shown in the following example, it will take up 16 bytes in total. Mind though, a single pointer takes 8 bytes and a char
takes one byte, so one would think the st1
struct must occupy 9 bytes. But it behaves as if all members are aligned to the largest member’s size (i.e. 8 bytes). st2
struct demonstrates a similar structure that occupies the same amount of memory, except that it has an array of 7 char
members.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char const *argv[]) {
typedef struct {
char *p;
char c2;
} st1;
typedef struct {
char *p;
char c2;
char padding[7];
} st2;
printf("sizeof st1 = %zu\n", sizeof(st1));
printf("sizeof st2 = %zu\n", sizeof(st2));
exit(EXIT_SUCCESS);
}
Output:
sizeof st1 = 16
sizeof st2 = 16
Use Member Reordering Technique to Save Space in Objects in C
The previous example demonstrates that there’s some waste of memory when structures include different types and don’t fill up the alignment boundaries. Although, there are some cases where it might be possible to reorder structure members and save extra space.
The next example code defines foo1
struct that has the largest member (char *
) in the middle and foo2
with the same member as the first one. The sizes of these two objects are different - 24 bytes and 16 bytes. This has to do with the ordering of the data members. In the foo1
structure, p
needs to be aligned at the address that is divisible by 8, so the int
and short
before it will occupy 8 bytes in total and two chars after it will occupy the 8 bytes as well. Although, if we move p
to the first place, the following members will squeeze into the 8 bytes and the alignment rule is satisfied as well. Thus, foo2
’s size totals 16 bytes and it’s called to be packed struct
. Note that the gcc
compiler has the special __attribute__ ((packed))
specifier that can force even unordered struct
members to be packed.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char const *argv[]) {
typedef struct {
int n1;
short s1;
char *p;
char c1;
char c2;
} foo1;
typedef struct {
char *p;
int n1;
short s1;
char c1;
char c2;
} foo2;
typedef struct {
int n1;
short s1;
char *p;
char c1;
char c2;
} __attribute__((packed)) foo3;
printf("sizeof foo1 = %zu\n", sizeof(foo1));
printf("sizeof foo2 = %zu\n", sizeof(foo2));
printf("sizeof foo3 = %zu\n", sizeof(foo3));
exit(EXIT_SUCCESS);
}
Output:
sizeof foo1 = 24
sizeof foo2 = 16
sizeof foo3 = 16
Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.
LinkedIn Facebook