By Manu


2010-11-29 17:16:12 8 Comments

Consider:

struct mystruct_A
{
   char a;
   int b;
   char c;
} x;

struct mystruct_B
{
   int b;
   char a;
} y;

The sizes of the structures are 12 and 8 respectively.

Are these structures padded or packed?

When does padding or packing take place?

8 comments

@snr 2019-03-09 10:45:37

There are no buts about it! Who want to grasp the subject must do the following ones,

@Eric Wang 2016-07-01 11:20:13

(The above answers explained the reason quite clear, but seems not totally clear about the size of padding, so, I will add an answer according to what I learn from The Lost Art of C Structure Packing)


Memory align (for struct)

Rules:

  • Before each individual member, there will be padding so that to make it start at an address that is divisible by its size.
    e.g on 64 bit system,int should start at address divisible by 4, and long by 8, short by 2.
  • char and char[] are special, could be any memory address, so they don't need padding before them.
  • For struct, other than the alignment need for each individual member, the size of whole struct itself will be aligned to a size divisible by size of largest individual member, by padding at end.
    e.g if struct's largest member is long then divisible by 8, int then by 4, short then by 2.

Order of member:

  • The order of member might affect actual size of struct, so take that in mind. e.g the stu_c and stu_d from example below have the same members, but in different order, and result in different size for the 2 structs.

Address in memory (for struct)

Rules:

  • 64 bit system
    Struct address starts from (n * 16) bytes. (You can see in the example below, all printed hex addresses of structs end with 0.)
    Reason: the possible largest individual struct member is 16 bytes (long double).

Empty space:

  • Empty space between 2 structs could be used by non-struct variables that could fit in.
    e.g in test_struct_address() below, the variable x resides between adjacent struct g and h.
    No matter whether x is declared, h's address won't change, x just reused the empty space that g wasted.
    Similar case for y.

Example

(for 64 bit system)

memory_align.c:

/**
 * Memory align & padding - for struct.
 * compile: gcc memory_align.c
 * execute: ./a.out
 */ 
#include <stdio.h>

// size is 8, 4 + 1, then round to multiple of 4 (int's size),
struct stu_a {
    int i;
    char c;
};

// size is 16, 8 + 1, then round to multiple of 8 (long's size),
struct stu_b {
    long l;
    char c;
};

// size is 24, l need padding by 4 before it, then round to multiple of 8 (long's size),
struct stu_c {
    int i;
    long l;
    char c;
};

// size is 16, 8 + 4 + 1, then round to multiple of 8 (long's size),
struct stu_d {
    long l;
    int i;
    char c;
};

// size is 16, 8 + 4 + 1, then round to multiple of 8 (double's size),
struct stu_e {
    double d;
    int i;
    char c;
};

// size is 24, d need align to 8, then round to multiple of 8 (double's size),
struct stu_f {
    int i;
    double d;
    char c;
};

// size is 4,
struct stu_g {
    int i;
};

// size is 8,
struct stu_h {
    long l;
};

// test - padding within a single struct,
int test_struct_padding() {
    printf("%s: %ld\n", "stu_a", sizeof(struct stu_a));
    printf("%s: %ld\n", "stu_b", sizeof(struct stu_b));
    printf("%s: %ld\n", "stu_c", sizeof(struct stu_c));
    printf("%s: %ld\n", "stu_d", sizeof(struct stu_d));
    printf("%s: %ld\n", "stu_e", sizeof(struct stu_e));
    printf("%s: %ld\n", "stu_f", sizeof(struct stu_f));

    printf("%s: %ld\n", "stu_g", sizeof(struct stu_g));
    printf("%s: %ld\n", "stu_h", sizeof(struct stu_h));

    return 0;
}

// test - address of struct,
int test_struct_address() {
    printf("%s: %ld\n", "stu_g", sizeof(struct stu_g));
    printf("%s: %ld\n", "stu_h", sizeof(struct stu_h));
    printf("%s: %ld\n", "stu_f", sizeof(struct stu_f));

    struct stu_g g;
    struct stu_h h;
    struct stu_f f1;
    struct stu_f f2;
    int x = 1;
    long y = 1;

    printf("address of %s: %p\n", "g", &g);
    printf("address of %s: %p\n", "h", &h);
    printf("address of %s: %p\n", "f1", &f1);
    printf("address of %s: %p\n", "f2", &f2);
    printf("address of %s: %p\n", "x", &x);
    printf("address of %s: %p\n", "y", &y);

    // g is only 4 bytes itself, but distance to next struct is 16 bytes(on 64 bit system) or 8 bytes(on 32 bit system),
    printf("space between %s and %s: %ld\n", "g", "h", (long)(&h) - (long)(&g));

    // h is only 8 bytes itself, but distance to next struct is 16 bytes(on 64 bit system) or 8 bytes(on 32 bit system),
    printf("space between %s and %s: %ld\n", "h", "f1", (long)(&f1) - (long)(&h));

    // f1 is only 24 bytes itself, but distance to next struct is 32 bytes(on 64 bit system) or 24 bytes(on 32 bit system),
    printf("space between %s and %s: %ld\n", "f1", "f2", (long)(&f2) - (long)(&f1));

    // x is not a struct, and it reuse those empty space between struts, which exists due to padding, e.g between g & h,
    printf("space between %s and %s: %ld\n", "x", "f2", (long)(&x) - (long)(&f2));
    printf("space between %s and %s: %ld\n", "g", "x", (long)(&x) - (long)(&g));

    // y is not a struct, and it reuse those empty space between struts, which exists due to padding, e.g between h & f1,
    printf("space between %s and %s: %ld\n", "x", "y", (long)(&y) - (long)(&x));
    printf("space between %s and %s: %ld\n", "h", "y", (long)(&y) - (long)(&h));

    return 0;
}

int main(int argc, char * argv[]) {
    test_struct_padding();
    // test_struct_address();

    return 0;
}

Execution result - test_struct_padding():

stu_a: 8
stu_b: 16
stu_c: 24
stu_d: 16
stu_e: 16
stu_f: 24
stu_g: 4
stu_h: 8

Execution result - test_struct_address():

stu_g: 4
stu_h: 8
stu_f: 24
address of g: 0x7fffd63a95d0  // struct variable - address dividable by 16,
address of h: 0x7fffd63a95e0  // struct variable - address dividable by 16,
address of f1: 0x7fffd63a95f0 // struct variable - address dividable by 16,
address of f2: 0x7fffd63a9610 // struct variable - address dividable by 16,
address of x: 0x7fffd63a95dc  // non-struct variable - resides within the empty space between struct variable g & h.
address of y: 0x7fffd63a95e8  // non-struct variable - resides within the empty space between struct variable h & f1.
space between g and h: 16
space between h and f1: 16
space between f1 and f2: 32
space between x and f2: -52
space between g and x: 12
space between x and y: 12
space between h and y: 8

Thus address start for each variable is g:d0 x:dc h:e0 y:e8

enter image description here

@Pervez Alam 2017-02-14 09:11:35

"Rules" actually made it very clear, I couldn't find straightforward rule anywhere. Thanks.

@Eric Wang 2017-02-14 12:42:05

@PervezAlam The book <The Lost Art of C Structure Packing>, explains the rules pretty well, even thought it's a little longer than this answer. The book is available freely online: catb.org/esr/structure-packing

@Pervez Alam 2017-02-14 13:02:13

I will give it a try, btw is it limited to Structure packing? Just curios as I liked the explanation in book.

@Eric Wang 2017-02-14 13:29:27

@PervezAlam It's a very short book, mainly focus on technology that would reduce memory footprint of c program, it takes only at most several days to finish reading.

@Akshay Immanuel D 2018-02-06 06:05:09

As per your first point: does that mean that padding is also added between structs. That is to make the first element of the next struct to a divisible address?

@Eric Wang 2018-02-06 12:15:03

@AkshayImmanuelD Yes, each individual member obey rule 1, and the start address of first member is also the start address of the struct itself.

@Akshay Immanuel D 2018-02-06 14:24:36

What happens to the padding bytes between 2 struct? Isn't that also a waste of memory?

@Eric Wang 2018-02-06 15:19:25

@AkshayImmanuelD To achieve alignment, padding is necessary. A well designed struct might contains proper amount of members in proper order, and the padding is minimized, thus that padding might won't be that significant for the overall memory.

@Akshay Immanuel D 2018-02-06 17:28:06

Makes sense why some coding standards say to arrange structures from largest to smallest members

@Akshay Immanuel D 2018-02-12 03:22:22

From my previous comment-> "does that mean that padding is also added between structs. That is to make the first element of the next struct to a divisible address". I read somewhere that padding can never be between structures. Padding at the end of one struct makes sure the beginning of the new struct is aligned

@Eric Wang 2018-02-12 13:59:27

@AkshayImmanuelD The space between 2 structs, don't actually belong to the first struct, because other non-struct variable could reuse it when possible. Check the updated answer, mainly the Address in memory - for struct part.

@Akshay Immanuel D 2018-02-12 14:06:44

So the compiler could place static duration variables in the gaps between structs

@Akshay Immanuel D 2018-08-24 09:43:55

So the size of a struct will always be an even number

@Validus Oculus 2018-10-29 03:32:00

I think "Address in memory - for struct" is not very clear, at least to me. It would help if you can explain a bit further.

@Eric Wang 2018-10-29 05:24:17

@ValidusOculus I modified the answer a bit, please check if it's more reasonable now.

@Validus Oculus 2018-10-29 06:17:28

@EricWang Thank you. I just realized that it was 'the possible' part in your sentence " the possible largest individual struct member is 16 bytes" therefore I was thinking where the hell 16 byte in that struct came from LOL. Thank you!

@Validus Oculus 2018-10-29 06:19:12

@EricWang For the part 'n * 16', what 'n' refers to? Do you mean that all the struct addresses starts from 16 byte aligned address?

@Eric Wang 2018-10-29 06:55:51

@ValidusOculus Yes, it means 16 byte aligned.

@Validus Oculus 2018-10-30 03:14:23

@Eric Wang Thank you!

@user2083050 2013-02-19 07:33:16

Structure packing suppresses structure padding, padding used when alignment matters most, packing used when space matters most.

Some compilers provide #pragma to suppress padding or to make it packed to n number of bytes. Some provide keywords to do this. Generally pragma which is used for modifying structure padding will be in the below format (depends on compiler):

#pragma pack(n)

For example ARM provides the __packed keyword to suppress structure padding. Go through your compiler manual to learn more about this.

So a packed structure is a structure without padding.

Generally packed structures will be used

  • to save space

  • to format a data structure to transmit over network using some protocol (this is not a good practice of course because you need to
    deal with endianness)

@IanC 2016-08-07 04:55:33

I know this question is old and most answers here explains padding really well, but while trying to understand it myself I figured having a "visual" image of what is happening helped.

The processor reads the memory in "chunks" of a definite size (word). Say the processor word is 8 bytes long. It will look at the memory as a big row of 8 bytes building blocks. Every time it needs to get some information from the memory, it will reach one of those blocks and get it.

Variables Alignment

As seem in the image above, doesn't matter where a Char (1 byte long) is, since it will be inside one of those blocks, requiring the CPU to process only 1 word.

When we deal with data larger than one byte, like a 4 byte int or a 8 byte double, the way they are aligned in the memory makes a difference on how many words will have to be processed by the CPU. If 4-byte chunks are aligned in a way they always fit the inside of a block (memory address being a multiple of 4) only one word will have to be processed. Otherwise a chunk of 4-bytes could have part of itself on one block and part on another, requiring the processor to process 2 words to read this data.

The same applies to a 8-byte double, except now it must be in a memory address multiple of 8 to guarantee it will always be inside a block.

This considers a 8-byte word processor, but the concept applies to other sizes of words.

The padding works by filling the gaps between those data to make sure they are aligned with those blocks, thus improving the performance while reading the memory.

However, as stated on others answers, sometimes the space matters more then performance itself. Maybe you are processing lots of data on a computer that doesn't have much RAM (swap space could be used but it is MUCH slower). You could arrange the variables in the program until the least padding is done (as it was greatly exemplified in some other answers) but if that's not enough you could explicitly disable padding, which is what packing is.

@David Foerster 2016-08-07 23:49:22

This doesn't explain structure packing but it illustrates CPU word alignment quite nicely.

@Ciro Santilli 新疆改造中心996ICU六四事件 2017-07-30 10:58:22

Did you draw that in paint? :-)

@IanC 2017-07-30 22:21:59

@CiroSantilli709大抓捕六四事件法轮功, it was on gimp, but I guess I'd have saved some time doing it on paint though haha

@Ciro Santilli 新疆改造中心996ICU六四事件 2017-07-30 22:25:23

Even better since open source (Y)

@manoj yadav 2015-08-15 15:25:46

Data structure alignment is the way data is arranged and accessed in computer memory. It consists of two separate but related issues: data alignment and data structure padding. When a modern computer reads from or writes to a memory address, it will do this in word sized chunks (e.g. 4 byte chunks on a 32-bit system) or larger. Data alignment means putting the data at a memory address equal to some multiple of the word size, which increases the system’s performance due to the way the CPU handles memory. To align the data, it may be necessary to insert some meaningless bytes between the end of the last data structure and the start of the next, which is data structure padding.

  1. In order to align the data in memory, one or more empty bytes (addresses) are inserted (or left empty) between memory addresses which are allocated for other structure members while memory allocation. This concept is called structure padding.
  2. 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.
  3. 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.
  4. Because of this structure padding concept in C, size of the structure is always not same as what we think.

@Artjom B. 2015-08-15 15:58:39

Why do you need to link to the same article 5 times in your answer? Please keep only one link to the example. Also, since you're linking to your article, you need to disclose that fact.

@Nikolai Fetissov 2010-11-29 17:24:02

Padding aligns structure members to "natural" address boundaries - say, int members would have offsets, which are mod(4) == 0 on 32-bit platform. Padding is on by default. It inserts the following "gaps" into your first structure:

struct mystruct_A {
    char a;
    char gap_0[3]; /* inserted by compiler: for alignment of b */
    int b;
    char c;
    char gap_1[3]; /* -"-: for alignment of the whole struct in an array */
} x;

Packing, on the other hand prevents compiler from doing padding - this has to be explicitly requested - under GCC it's __attribute__((__packed__)), so the following:

struct __attribute__((__packed__)) mystruct_A {
    char a;
    int b;
    char c;
};

would produce structure of size 6 on a 32-bit architecture.

A note though - unaligned memory access is slower on architectures that allow it (like x86 and amd64), and is explicitly prohibited on strict alignment architectures like SPARC.

@Hi-Angel 2014-05-24 09:19:08

I wonder: is prohibition of unaligned memory on the spark means that it can not deal with an usual byte arrays? Struct packing as I know mostly used in transmitting(i.e networking) a data, when you need to cast a byte array to a struct, and be sure that an array fit to a struct fields. If the spark can not do that, how those working at all?!

@Nikolai Fetissov 2014-05-24 15:09:04

That's exactly why, if you look at IP, UDP, and TCP header layouts, you'd see that all integer fields are aligned.

@Rob11311 2014-06-29 16:45:40

The "Lost Art of C Structure Packing" explains padding and packing ptimisations - catb.org/esr/structure-packing

@iDebD_gh 2015-02-17 10:01:04

/* malloc() always provides aligned memory / cptr = malloc(sizeof(int) + 1); / Increment the pointer by one, making it misaligned / iptr = (int *) ++cptr; / Dereference it as an int pointer, causing an unaligned access */ *iptr = 42; Above code will give bus error. But if I stopped packing of a structure, accessing its variables will not give any ? Why?

@Nikolai Fetissov 2015-02-17 15:23:22

Post a question.

@JoshJ 2015-05-07 18:58:11

This may have just saved my day. Was wondering why the hell my struct using fwrite was always aligning along 32-bit boundaries. Thanks for the detailed answer and the packed attribute.

@allyourcode 2015-07-30 01:23:27

Does first member have to come first? I thought arragement is totally up to the implementation, and cannot be relied upon (even from version to version).

@Philip Couling 2016-04-06 15:33:13

@allyourcode I believe you may be right in terms of the C standard, however when you pack a structure no compiler will mess with the order of fields. The whole purpose of packing is to give the programmer control over what the structure looks like in memory.

@parasrish 2017-04-24 10:45:52

good read : geeksforgeeks.org/…

@martinkunev 2017-12-08 14:32:34

+allyourcode The standard guarantees that the order of the members will be preserved and that the first member will start at 0 offset.

@Donghua Liu 2018-11-16 07:42:42

the sizeof struct attribute__((__packed)) mystruct_A { char a; int b; char c; }; in my computer give me 9

@nmichaels 2010-11-29 17:23:29

Structure packing is only done when you tell your compiler explicitly to pack the structure. Padding is what you're seeing. Your 32-bit system is padding each field to word alignment. If you had told your compiler to pack the structures, they'd be 6 and 5 bytes, respectively. Don't do that though. It's not portable and makes compilers generate much slower (and sometimes even buggy) code.

@casablanca 2010-11-29 17:23:05

Padding and packing are just two aspects of the same thing:

  • packing or alignment is the size to which each member is rounded off
  • padding is the extra space added to match the alignment

In mystruct_A, assuming a default alignment of 4, each member is aligned on a multiple of 4 bytes. Since the size of char is 1, the padding for a and c is 4 - 1 = 3 bytes while no padding is required for int b which is already 4 bytes. It works the same way for mystruct_B.

Related Questions

Sponsored Content

10 Answered Questions

[SOLVED] Improve INSERT-per-second performance of SQLite?

5 Answered Questions

[SOLVED] Is gcc's __attribute__((packed)) / #pragma pack unsafe?

  • 2011-12-19 22:28:00
  • Keith Thompson
  • 103313 View
  • 139 Score
  • 5 Answer
  • Tags:   c gcc pragma-pack

28 Answered Questions

[SOLVED] When to use struct?

  • 2009-02-06 17:37:55
  • Alex Baranosky
  • 245521 View
  • 1296 Score
  • 28 Answer
  • Tags:   c# struct

16 Answered Questions

[SOLVED] When to use margin vs padding in CSS

  • 2010-02-03 03:20:12
  • Alex Angas
  • 696225 View
  • 2141 Score
  • 16 Answer
  • Tags:   css padding margin

11 Answered Questions

[SOLVED] Why isn't sizeof for a struct equal to the sum of sizeof of each member?

0 Answered Questions

What is the alignment of a packed structure in C?

2 Answered Questions

1 Answered Questions

[SOLVED] Why g++ isn't performing structure packing here?

2 Answered Questions

[SOLVED] Avoiding structure padding in c using __attribute__((packed))

  • 2015-08-14 15:57:23
  • theartist33
  • 907 View
  • 8 Score
  • 2 Answer
  • Tags:   c struct

1 Answered Questions

[SOLVED] Structure padding and element access

Sponsored Content