Why Is Padding Added for Multiple Data Members of Structures and Not for Single Members

Why is padding added for multiple data members of structures and not for single members?

Padding is added in the second case because, on your machine, an int is aligned to 4 bytes. So it has to reside at an address that is divisible to 4.

0x04   0x05   0x06   0x07   0x08   0x09   0x0A   0x0B

a b b b b

If no padding is added, the int member starts at address 0x05, which is wrong. With 3 added padding bytes:

0x04   0x05   0x06   0x07   0x08   0x09   0x0A   0x0B

a | padding | b b b b

Now the int is at 0x08, which is OK.

Why is there no padding in the structure for only char type members?

The padding in structure exist (mostly) to enforce that the individual members are aligned to their fundamental alignment requirement, i.e. (C11 3.2p1):

requirement that objects of a particular type be located on storage boundaries with addresses that are particular multiples of a byte address

The padding in the middle and at the end of the structure is used to ensure that even within an array of these structures, each member will be still aligned according to their alignment requirement. C11 6.2.8p1:

Complete object types have alignment requirements which place restrictions on the addresses at which objects of that type may be allocated. An alignment is an implementation-defined integer value representing the number of bytes between successive addresses at which a given object can be allocated. An object type imposes an alignment requirement on every object of that type: stricter alignment can be requested using the _Alignas keyword.

Now, the alignment requirement of every other type is implementation-defined, but one thing is implied: since the alignment requirement is expressed in size_t; sizeof (char) is 1, and pointers to character types can be used to address each individual character in other types, a character type cannot have a fundamental alignment requirement of more than 1. Surprisingly this is not spelt out in the C standard at all; it just has this this vague wording (C11 6.2.8p6):

The types char, signed char, and unsigned char shall have the weakest alignment requirement.

As the alignment of char is at most 1, the compiler need not add any padding, because even if the structure is exactly 5 bytes long, then even in an array, with some structures starting at odd address, each of the members of those structures would still be properly aligned.

When do structures not have padding?

The predominant use of padding is to align structure members as required by the hardware (or other aspects of the C implementation). An algorithm for laying out data in a struct is in this answer.

To answer the question in your title, when do structures not have padding: A structure does not require padding for alignment if each member’s alignment requirement is a divisor of the total size of all preceding members and of the total size of all members. (A C implementation may still add padding for reasons other than alignment, but that is a bit unusual.)

For your examples, let’s suppose, in a C implementation, short is two bytes in size and requires two-byte alignment. By definition, char is one byte and requires one-byte alignment.

Then, in struct s {short c;}:

  • c is put at the beginning of the struct. There is never any padding at the beginning.
  • If we make an array of these struct, the next struct s will begin two bytes beyond the first, and its member c will still be at a multiple of two bytes, so it is aligned correctly.
  • Therefore, we do not need any padding to make this work.

In contrast, in struct s {short c; char a;}:

  • c is put at the beginning.
  • a is put two bytes after c. This is fine, since a only requires one-byte alignment.
  • If we do not add any padding, the size of the struct is three bytes. Then, if we make an array of these struct, the next struct s will begin three bytes from the start.
  • In that second struct s, the c member will be at an offset of three bytes. That violates the alignment requirement for short.
  • Therefore, to make this struct work, we must add one byte of padding. This makes the total size four bytes. Then, in an array of these struct, all the members will be at boundaries required by their alignment.

Even if you declare just a single object of a structure, as in struct s {short c; char a;} x;, a structure is always laid out so it can be used in an array.

Structure padding and packing

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.

Is padding ever added to this C structure?

Compiler implementations are allowed to add any padding in a structure between fields or after the final field.

It probably won't in this case, since you only have one data type, but there's no guarantee that it won't.

If you need to control implementation-specific behavior, many implementations will give you that level of control, such as with #pragma pack, for example.

Even if you don't have that level of control, you can use standard features to at least catch the problem at compile time (C11 or better):

#include <assert.h>
typedef struct { double data[2]; } my_struct;
static_assert(sizeof(my_struct) == sizeof(double) * 2, "I do not like padding");

Padding logic of 'double' struct members on 32-bits machines

I am absolutely no expert, so if I'm wrong I'd love to know more too, but one reason I've seen to force double alignment on 8 bytes, is because of the cpu cache. If doubles were put on 4 byte alignments, the cache may only get half of the double and force more reads. By forcing alignment of 8 bytes, it makes sure that a single cache line is used to read the whole double.

This question is similar, why is data structure alignment important for performance? and some of the answers given may explain this better than I can for you.

Why this inconsistency in padding data members?

Imagine you have an Array of As. The second A in the array would have its member b misaligned if there was no additional padding. That said the compiler can choose whatever it feels like. Misaligned accesses cost runtime, padding costs space. Your compiler favored runtime.



Related Topics



Leave a reply



Submit