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
, andunsigned 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 thestruct
. There is never any padding at the beginning.- If we make an array of these
struct
, the nextstruct s
will begin two bytes beyond the first, and its memberc
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 afterc
. This is fine, sincea
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 thesestruct
, the nextstruct s
will begin three bytes from the start. - In that second
struct s
, thec
member will be at an offset of three bytes. That violates the alignment requirement forshort
. - 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 thesestruct
, 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 A
s. 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
Changing the Current Directory in Linux Using C++
C-Style Strings as Template Arguments
End of File(Eof) of Standard Input Stream (Stdin)
Colorizing Text in the Console with C++
How to Simulate "Press Any Key to Continue"
Change Floating Point Rounding Mode
How to Have an Unordered_Map Where the Value Type Is the Class It's In
Getting Libcurl to Work with Visual Studio 2013
Using C++ Filestreams (Fstream), How to Determine the Size of a File
How to Compile SQLite with Icu
Get Memory Overflow Caused by a Memory Leak and the Application Keep Running and Allocating
Q_Object Throwing 'Undefined Reference to Vtable' Error
Is String::C_Str() No Longer Null Terminated in C++11
Drawing Sphere in Opengl Without Using Glusphere()
Is There Any "Standard" Htonl-Like Function for 64 Bits Integers in C++