🌐
Cppreference
en.cppreference.com › w › c › language › object.html
Objects and alignment - cppreference.com
January 31, 2025 - Note that type-punning may also ... property called alignment requirement, which is an integer value of type size_t representing the number of bytes between successive addresses at which objects of this type can be allocated....
way in which data is arranged and accessed in computer memory
Data structure alignment is the way data is arranged and accessed in computer memory. It consists of three separate but related issues: data alignment, data structure padding, and packing. The CPU in … Wikipedia
🌐
Wikipedia
en.wikipedia.org › wiki › Data_structure_alignment
Data structure alignment - Wikipedia
February 10, 2026 - Data structure alignment is the way data is arranged and accessed in computer memory. It consists of three separate but related issues: data alignment, data structure padding, and packing. The CPU in modern computer hardware performs reads and writes to memory most efficiently when the data ...
Discussions

Structure Alignment? CUDA Structure Alignment differs?
I’m using a 64-bit Linux so pointers are 8 byte long. After thinking it through it appears CUDA adds more padding than is actually needed. So my guess is it adds extra padding to the float3s and the ints, struct __align__(16) MyStruct { float3 a; //12 float3 b; //12 float3 ... More on forums.developer.nvidia.com
🌐 forums.developer.nvidia.com
0
0
July 31, 2008
Structures in C: From Basics to Memory Alignment
There's one gotcha here, which is that the alignment requirements of the flexible array member can change the size of the struct. For example the following fails on x86_64-linux-gnu: · struct flexible_char { char c; char arr[]; }; struct flexible_int { char c; int arr[]; }; _Static_assert... More on news.ycombinator.com
🌐 news.ycombinator.com
57
293
July 1, 2023
How does data structure alignment help in efficient reading of memory?
Structure alignment tries it's best to align structures to fall within certain boundaries. Specifically memory words. Most address schemes are aligned on word boundaries so if you don't align to them you have to have an (another) offset to find the start of a structure/ field, which takes more instructions and time. You also have caches to deal with, which always read in a certain amount of words, typically called a cache line with is typically measured in memory blocks. The same thing happens if you don't align fields in your structure to at least word boundaries. It can be very expensive if you go across cache line boundaries for a field, especially if one of your lookups results in a cache miss. Now like you said, a lot of structures are too big to fit in a cache line. But it still helps to align their fields to a word boundary because you still don't want to also have to figure out the offset within the word. This is why structs in c/c++ will pad fields typically to boundaries of the highest native type. It just makes book keeping easier/faster. Us humans operate the same way. If you are counting by 4s it's much easier to count by 4 all the time than to count by 4 to a certain point then change to counting by ones. More on reddit.com
🌐 r/computerscience
9
49
December 22, 2021
c - Structure padding and packing - Stack Overflow
The sizes of the structures are 12 and 8 respectively. ... @Paolo, that Lost Art link does not show what happens when there is pointer-alignment and the above where two ints might be one after another. More on stackoverflow.com
🌐 stackoverflow.com
Top answer
1 of 10
67

At least on most machines, a type is only ever aligned to a boundary as large as the type itself [Edit: you can't really demand any "more" alignment than that, because you have to be able to create arrays, and you can't insert padding into an array]. On your implementation, short is apparently 2 bytes, and int 4 bytes.

That means your first struct is aligned to a 2-byte boundary. Since all the members are 2 bytes apiece, no padding is inserted between them.

The second contains a 4-byte item, which gets aligned to a 4-byte boundary. Since it's preceded by 6 bytes, 2 bytes of padding is inserted between v3 and i, giving 6 bytes of data in the shorts, two bytes of padding, and 4 more bytes of data in the int for a total of 12.

2 of 10
23

Forget about having different members, even if you write two structs whose members are exactly same, with a difference is that the order in which they're declared is different, then size of each struct can be (and often is) different.

For example, see this,

#include <iostream>
using namespace std;
struct A
{
   char c;
   char d;
   int i; 
};
struct B
{
   char c;
   int i;   //note the order is different!
   char d;
};
int main() {
        cout << sizeof(A) << endl;
        cout << sizeof(B) << endl;
}

Compile it with gcc-4.3.4, and you get this output:

8
12

That is, sizes are different even though both structs has same members!

Code at Ideone : http://ideone.com/HGGVl

The bottomline is that the Standard doesn't talk about how padding should be done, and so the compilers are free to make any decision and you cannot assume all compilers make the same decision.

🌐
Devtrovert
blog.devtrovert.com › p › struct-optimization-a-small-change
Optimize Your Struct with Alignment Trick - by Phuong Le
August 25, 2023 - If this does not make sense to you, let’s look at the int32 type which has an alignment of 4 bytes. This means int32 variables must be stored at memory addresses that are multiples of 4. So valid addresses would be 0, 4, 8, 12, and so forth. ... type StructA struct { A byte B int32 C byte D int64 E int32 } // 4 fmt.Println("align of int32", unsafe.Alignof(s.B)) // 4 fmt.Println("address offset 1:", unsafe.Offsetof(s.B)) // 24 fmt.Println("address offset 2:", unsafe.Offsetof(s.E))
🌐
W3Schools
w3schools.com › c › c_structs_padding.php
C Struct Alignment and Padding
The compiler may add padding bytes to align data properly. The total struct size is often larger than the sum of its members.
🌐
GeeksforGeeks
geeksforgeeks.org › c language › structure-member-alignment-padding-and-data-packing
Structure Member Alignment, Padding and Data Packing - GeeksforGeeks
In order to avoid such misalignment, the compiler introduces alignment requirements to every structure. It will be as that of the largest member of the structure. In our case alignment of structa_t is 2, structb_t is 4 and structc_t is 8.
Published   July 29, 2025
🌐
NVIDIA Developer Forums
forums.developer.nvidia.com › accelerated computing › cuda › cuda programming and performance
Structure Alignment? CUDA Structure Alignment differs? - CUDA Programming and Performance - NVIDIA Developer Forums
July 31, 2008 - I’m using a 64-bit Linux so pointers are 8 byte long. After thinking it through it appears CUDA adds more padding than is actually needed. So my guess is it adds extra padding to the float3s and the ints, struct __align__(16) MyStruct { float3 a; //12 float3 b; //12 float3 ...
Find elsewhere
🌐
GitConnected
levelup.gitconnected.com › how-struct-memory-alignment-works-in-c-3ee897697236
How Struct Memory Alignment Works in C | by Mazin Mohamed | Level Up Coding
February 14, 2023 - Alignment of struct is done automatically by the compiler, since aligned data is much faster to access by the CPU. Struct alignment is achieved by dividing struct memory space into equally sized segments. The size of each segment is the size ...
🌐
Microsoft Learn
learn.microsoft.com › en-us › cpp › build › reference › zp-struct-member-alignment
/Zp (Struct Member Alignment) | Microsoft Learn
October 3, 2025 - Controls how the members of a structure are packed into memory and specifies the same packing for all structures in a module.
🌐
Catb
catb.org › esr › structure-packing
The Lost Art of Structure Packing
Compilers do this as the easiest way to ensure that all the members are self-aligned for fast access. Also, in C (and Go, and Rust) the address of a struct is the same as the address of its first member - there is no leading padding.
🌐
Medium
medium.com › @haadimdwork › c-struct-padding-and-alignment-85b2011d1f5a
C Struct Padding And Alignment. 1.1 Introduction | by Haadi Mohammed | Medium
February 12, 2025 - After uint8_t which is of 1 byte, we are at an unaligned memory address for an uint32_t datatype, so we perform padding or add 3 padded bytes to ensure uint32_t starts at an aligned offset and it is aligned to the 4-byte boundary. Similarly, then we add char which is of 1-byte uint8_t. We then add 4 padding bytes at the end as there needs to be additional padding after it to ensure the size of the struct is a multiple of the alignment of the largest member (uint32_, 4 bytes).This rule ensures that each instance of the struct will be properly aligned in memory & the next instance of the struct in an array will also be aligned properly.
🌐
Hacker News
news.ycombinator.com › item
Structures in C: From Basics to Memory Alignment | Hacker News
July 1, 2023 - There's one gotcha here, which is that the alignment requirements of the flexible array member can change the size of the struct. For example the following fails on x86_64-linux-gnu: · struct flexible_char { char c; char arr[]; }; struct flexible_int { char c; int arr[]; }; _Static_assert...
🌐
Reddit
reddit.com › r/computerscience › how does data structure alignment help in efficient reading of memory?
r/computerscience on Reddit: How does data structure alignment help in efficient reading of memory?
December 22, 2021 -

I know that data structure alignment is done to prevent a data structure being stored across two memory blocks. This was explained by u/AuntieSauce in another post I created regarding the internal working of structs.

Now, why does the second rule ensure we don’t have one element of a struct stretched across two blocks? Here is an example: lets say we have a struct that an 8 byte element and a 1 byte element:

| 8 bytes | 1 byte

Now, lets say we want to make an array of structs. Each struct is 8 bytes in size, and arrays are stored contiguously in memory, so we have

8+1 bytes | 8+1 bytes | 8+1 bytes | etc…

If our array is large enough we will eventually approach the end of a block. Will a block size ever be divisible by 9? Like, almost definitely not. So you’ll get the end of the block with less than 9 bytes of space left, and the struct will get chopped!

In the Wikipedia article about data structure alignment, it is written that CPU can efficiently read memory when it is data structure aligned.

The CPU in modern computer hardware performs reads and writes to memory most efficiently when the data is naturally aligned, which generally means that the data's memory address is a multiple of the data size

So my question is that how does data structure alignment actually help in the efficient memory reads by the CPU.

Thanks!

Top answer
1 of 4
8
Structure alignment tries it's best to align structures to fall within certain boundaries. Specifically memory words. Most address schemes are aligned on word boundaries so if you don't align to them you have to have an (another) offset to find the start of a structure/ field, which takes more instructions and time. You also have caches to deal with, which always read in a certain amount of words, typically called a cache line with is typically measured in memory blocks. The same thing happens if you don't align fields in your structure to at least word boundaries. It can be very expensive if you go across cache line boundaries for a field, especially if one of your lookups results in a cache miss. Now like you said, a lot of structures are too big to fit in a cache line. But it still helps to align their fields to a word boundary because you still don't want to also have to figure out the offset within the word. This is why structs in c/c++ will pad fields typically to boundaries of the highest native type. It just makes book keeping easier/faster. Us humans operate the same way. If you are counting by 4s it's much easier to count by 4 all the time than to count by 4 to a certain point then change to counting by ones.
2 of 4
5
Caching is a huge factor of why you dont want your data striped across memory. The ability to fetch data from the cache is often times order(s) of magnitude faster than fetching from memory, which is in turn order(s) of magnitude faster than fetching from a hard drive (HDDs at least). So reducing the number of times you have to go get data from somewhere else, the better. If you are dealing with very large datasets, where you can’t fit all of the data into the cache, then knowing how data is read from memory/disk becomes more important. For example, execution times while looping over large 2D arrays will vary widely depending on which array is iterated in the outer loop, and which array is iterated in the inner loop.
🌐
Microsoft Learn
learn.microsoft.com › en-us › cpp › c-language › storage-and-alignment-of-structures
Storage and Alignment of Structures | Microsoft Learn
July 26, 2023 - Structure members are stored ... Every data object has an alignment-requirement. For structures, the requirement is the largest of its members....
🌐
Microsoft Learn
learn.microsoft.com › en-us › cpp › cpp › alignment-cpp-declarations
Alignment | Microsoft Learn
November 2, 2023 - By default, the compiler aligns class and struct members on their size value: bool and char on 1-byte boundaries, short on 2-byte boundaries, int, long, and float on 4-byte boundaries, and long long, double, and long double on 8-byte boundaries.
🌐
Abstract Expression
abstractexpr.com › 2023 › 06 › 29 › structures-in-c-from-basics-to-memory-alignment
Structures in C: From Basics to Memory Alignment – Abstract Expression
February 8, 2024 - Add a 4 and the shorts and the ints are fine and only the 8-byte types live in two different machine words. And here we already see the solution. A structure has to get enough trailing padding to align with its biggest data type.
Top answer
1 of 11
404

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.

2 of 11
165

(The above answers explained the reason quite clearly, but seems not totally clear about the size of padding, so, I will add an answer according to what I learned from The Lost Art of Structure Packing, it has evolved to not limit to C, but also applicable to Go, Rust.)


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 alignment requirement.
    E.g., on many systems, an int should start at an address divisible by 4 and a 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 strictest alignment requirement of any of its members, by padding at end.
    E.g., on many systems, if struct's largest member is int then by divisible by 4, if 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)

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

🌐
Medium
medium.com › @aliaksandr.kavalchuk › с-interview-questions-structure-alignment-in-c-07c8ea7e1d27
С interview questions. Structure alignment in c | by Aliaksandr Kavalchuk | Medium
April 6, 2024 - That is, 1-byte fields are not aligned, 2-byte fields are aligned to even positions, 4—byte fields are aligned to multiples of four, etc. ... struct ExampleStruct_t { uint8_t a; uint8_t padding1; uint16_t b; uint8_t c; uint8_t padding2; uint8_t padding3; uint8_t padding4; uint32_t d; uint8_t e; uint8_t padding5; uint8_t padding6; uint8_t padding7; };
🌐
Reddit
reddit.com › r/cpp_questions › how does struct alignment work?
r/cpp_questions on Reddit: How does struct alignment work?
April 15, 2024 -

I have a struct that inherits from a 16 byte aligned struct:

struct __declspec( align(16) ) SLIST_ENTRY 
{ 
    struct SLIST_ENTRY* Next; 
};
struct CListEntry : SLIST_ENTRY { void* p; };

C_ASSERT( sizeof  ( CListEntry )    == sizeof( void* ) * 4 ); 
C_ASSERT( offsetof( CListEntry, p ) == sizeof( void* ) * 2 );

I don't understand why both assertions succeed, p could be placed immediately after Next and CListEntry would still have 16 byte alignment. Even weirder is when I compile the code:

CListEntry* pListEntry; // mov rax, qword ptr [pListEntry]
void*       p;          // mov rcx, qword ptr [p]
pListEntry->p = p;      // mov qword ptr [rax+8], rcx

And in the debugger window I see ( (char*)pListEntry + 8 ) being updated, not ( (char*)pListEntry + 16 ) as the assertions suggest. What's going on?

🌐
Grandidierite
grandidierite.github.io › structure-alignment-and-packing-in-C-programming
Structure Alignment and Packing in C Programming | Tachyon
July 6, 2018 - NIL can be specified as either __attribute__((aligned())) or __attribute__((aligned)), the compiler automatically sets the alignment for the declared variable or field to the largest alignment · __attribute__((packed)) , this attribute specifies that a variable or structure field should have the smallest possible alignment – one byte for a variable and one bit for a field