Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 29

Understanding Struct Size and Padding

Recommended resources

Welcome back!

In our previous lesson, we established the fundamental rules of data alignment and structure padding. We learned that compilers insert padding bytes to ensure every member is aligned for efficient CPU access, and that the entire structure receives trailing padding to ensure correct alignment within an array.

Today, we will put that theory into practice. Your goal for this lesson is to master a skill frequently tested in C-focused interviews: calculating the size of a struct, including padding, given its member types and alignment rules. This involves applying the rules from our last session in a systematic way to predict the exact output of the sizeof operator.

1. The Rules of Calculation

Let's quickly recap and formalize the process for calculating a struct's size. For any given struct, you'll follow these three steps on a target architecture (we'll assume a common 64-bit system where char=1, short=2, int=4, double=8 bytes):

  1. Determine Struct Alignment: The alignment requirement for the entire struct is dictated by its largest member. For example, if a struct's largest member is a double, the struct itself must be 8-byte aligned.

  2. Place Each Member Sequentially: Go through the members in the order they are declared. For each member:

    • Find its individual alignment requirement.
    • The member's starting address (offset) within the struct must be a multiple of its alignment.
    • If the current offset is not suitable, the compiler adds padding bytes until it is.
    • Place the member and advance the current offset by its size.
  3. Add Trailing Padding: After placing the last member, the total size of the struct must be a multiple of its overall alignment (from Step 1). If it's not, the compiler adds padding bytes at the end until it is.

Let's see this process in action by analyzing some examples.

Structure Member Alignment, Padding and Data Packing

This article from GeeksforGeeks is perfect for our task. It presents several structs, shows their actual sizes using sizeof, and then provides a byte-by-byte analysis explaining how padding leads to those sizes. This will help you see the rules we've discussed applied to concrete code.

First, read the section 'Structure Padding in C'. Note the difference between the naively calculated sizes and the actual sizes printed by the program. Then, read the detailed analysis for Structure A, Structure B, and Structure C. Focus on how the compiler calculates the offset for each member and adds padding where necessary.


2. A Worked Example: structc_t

After reading the article, you saw the analysis for several structs. Let's formalize the calculation for structc_t together, as it demonstrates all the rules clearly.

// Assuming 64-bit system: char=1, double=8, int=4
typedef struct structc_tag {
    char   c;
    double d;
    int    s;
} structc_t;

Calculation Breakdown:

  1. Struct Alignment: The largest member is double d (8 bytes). Therefore, sizeof(structc_t) must be a multiple of 8.

  2. Member Placement:

    • char c;
      • Alignment: 1 byte.
      • Placed at offset 0. It occupies 1 byte.
      • Current offset is now 1.
    • double d;
      • Alignment: 8 bytes.
      • The current offset is 1, which is not a multiple of 8. The compiler must pad.
      • The next valid offset is 8. So, 7 padding bytes are inserted after c.
      • d is placed at offset 8. It occupies 8 bytes.
      • Current offset is now 8 + 8 = 16.
    • int s;
      • Alignment: 4 bytes.
      • The current offset is 16, which is a multiple of 4. No padding is needed.
      • s is placed at offset 16. It occupies 4 bytes.
      • Current offset is now 16 + 4 = 20.
  3. Trailing Padding:

    • The total size after all members is 20 bytes.
    • The struct's alignment requirement is 8 bytes.
    • 20 is not a multiple of 8. The next multiple of 8 is 24.
    • The compiler adds 4 bytes of trailing padding.

Final Size: The total size is 1 (char) + 7 (pad) + 8 (double) + 4 (int) + 4 (pad) = 24 bytes.

The following image provides a detailed visualization of a similar process. You can see the colored blocks for data members and the gray blocks for padding bytes, all laid out along memory addresses.

Memory Representation of struct s1 with Padding
This image shows the memory layout of a struct, visually representing how each member is placed according to its alignment. The gray areas clearly mark the padding bytes inserted by the compiler, both between members and at the end of the struct, to satisfy alignment rules.

3. Practice Problems

Now it's your turn. This is exactly what an interviewer might ask you to do on a whiteboard. Calculate the sizeof the following structs, assuming a 64-bit architecture (char=1, short=2, int=4, long long=8).

Problem 1:

struct problem1 {
    char      a;
    int       b;
    char      c;
    short     d;
};

Think it through... what's the size?

Click to see the solution
  • Struct Alignment: The largest member is int b (4 bytes). The total size must be a multiple of 4.
  • Member Placement:
    • char a; at offset 0. (Current offset: 1)
    • int b; needs 4-byte alignment. Add 3 padding bytes. b is at offset 4. (Current offset: 8)
    • char c; at offset 8. (Current offset: 9)
    • short d; needs 2-byte alignment. Add 1 padding byte. d is at offset 10. (Current offset: 12)
  • Trailing Padding: The current size is 12, which is already a multiple of the struct's alignment (4). No trailing padding is needed.
  • Final Size: 12 bytes.

Problem 2:

struct problem2 {
    long long a;
    char      b;
    int       c;
};

Calculate the size.

Click to see the solution
  • Struct Alignment: The largest member is long long a (8 bytes). The total size must be a multiple of 8.
  • Member Placement:
    • long long a; at offset 0. (Current offset: 8)
    • char b; at offset 8. (Current offset: 9)
    • int c; needs 4-byte alignment. Add 3 padding bytes. c is at offset 12. (Current offset: 16)
  • Trailing Padding: The current size is 16, which is a multiple of the struct's alignment (8). No trailing padding is needed.
  • Final Size: 16 bytes.

This systematic calculation is key. In an interview, being able to walk through these steps confidently demonstrates a solid grasp of C's memory model, which is essential for low-level development. Your work on communication stacks, where software structures must perfectly match protocol-defined data units, is a direct application of this principle. Any miscalculation of padding would lead to data corruption when serializing or deserializing packets.


Conclusion

In this lesson, we transitioned from the theory of padding to the practical skill of calculating a struct's size. You now have a reliable, step-by-step method to determine the memory footprint of any C struct.

Key Takeaways:

  • Systematic Calculation: To find sizeof(struct), you must follow a three-step process: determine the struct's overall alignment, place each member sequentially while adding internal padding, and finally add trailing padding to satisfy the struct's alignment.
  • Two Types of Padding: Remember that padding can appear both between members (internal padding) and at the end of the struct (trailing padding).
  • Alignment is Key: Every calculation hinges on two alignment values: the alignment of the member being placed and the overall alignment of the entire struct.

The examples in this lesson hint at an important consequence: the order of members matters. In our next lesson, we will explore exactly this: predicting how reordering struct members can change the total size and padding. This is the next logical step, moving from just calculating size to actively optimizing it.