Students add the declared member sizes, get one total, and then see a larger sizeof in the answer key. The missing bytes are usually padding inserted to satisfy alignment. Once you place each member at a valid offset, structure and union size questions become a mechanical layout exercise.
The alignment rules that decide the layout
Take a model where char is 1 byte, short is 2, int is 4, double is 8, and each type's required alignment equals its own size. A real implementation can differ, so a question's stated model or target ABI always takes priority.
Apply three rules in order:
Each member begins at an offset that is a multiple of its required alignment.
The structure's alignment is the greatest alignment required by any member.
After the last member, the total size is rounded up to a multiple of the structure's alignment.
Padding between members is internal padding. Bytes added at the end are tail padding. Tail padding matters because every element of an array of structures must begin at a correctly aligned address.
Do not guess from a familiar machine. Write an offset counter, align it before each member, add the member's size, and round the final counter once.
Worked structure padding computation
Consider:
struct A {
char c;
int i;
char d;
double e;
};Start at offset 0.
cneeds alignment 1, so it occupies byte 0. The next free offset is 1.ineeds alignment 4. The next multiple of 4 is 4, so offsets 1, 2, and 3 are three padding bytes.ioccupies offsets 4 through 7.dneeds alignment 1, so it occupies offset 8. The next free offset is 9.eneeds alignment 8. The next multiple of 8 is 16, so offsets 9 through 15 contribute seven padding bytes.eoccupies offsets 16 through 23.
The widest alignment is 8. The next free offset is 24, already a multiple of 8, so no tail padding is needed. Therefore:
member bytes = 1 + 4 + 1 + 8 = 14
internal padding = 3 + 7 = 10
total size = 14 + 10 = 24 bytes
sizeof(struct A) = 24The cross-check is the final range: offsets 0 through 23 contain exactly 24 bytes. Fourteen data bytes plus ten padding bytes also gives 24.

This same offset method supports the pointer diagrams used in Pointers in C for GATE. A pointer may lead to an object, but the object's members still live at offsets decided by its layout.
Reorder members to reduce padding
Keep the same data but place the widest members first:
struct B {
double e;
int i;
char c;
char d;
};Now e occupies offsets 0 through 7. i can begin immediately at aligned offset 8 and occupies 8 through 11. c and d use offsets 12 and 13.
The member total is still 14 bytes. Offset 14 is not a multiple of the widest alignment, 8, so offsets 14 and 15 become two tail-padding bytes. The final size is 16 bytes.
sizeof(struct A) = 24
sizeof(struct B) = 16
saving per object = 24 - 16 = 8 bytesCheck it another way: 14 member bytes plus 2 tail-padding bytes equals 16. Reordering has reduced padding from 10 bytes to 2, which saves 8 bytes while preserving the members.
A useful heuristic is widest to narrowest. It often minimises gaps, though exact layout still belongs to the implementation and nested members may introduce extra constraints.
Unions place every member at offset zero
A structure gives each member its own storage. A union gives all members the same starting address and enough storage for its largest member.
union U {
char c;
int i;
double e;
};On the stated model, c uses byte 0, i uses bytes 0 through 3, and e uses bytes 0 through 7. The largest size and alignment are both 8, so sizeof(union U) = 8, not 1 + 4 + 8 = 13.

Writing u.i and then examining u.c exposes the byte at the start of the shared storage. Whether that is the low-order or high-order byte depends on endianness, and portable code should not assume one byte order. Reading a member other than the one last written is type punning, and the value it yields depends on the representation, so keep the size calculation separate from any claim about portability.
Self-referential structures and linked lists
A structure cannot contain an object of its own type by value. If struct Node contained another complete struct Node, that member would need another node inside it forever, so no finite size could be chosen.
It can contain a pointer to its own type because a pointer has a known, finite size:
struct Node {
int data;
struct Node *next;
};Extend the model with an 8-byte pointer aligned to 8. data occupies offsets 0 through 3. The pointer must begin at offset 8, so offsets 4 through 7 are padding. next occupies offsets 8 through 15. The structure size is 16 bytes: 4 + 4 padding + 8 = 16.
Reordering does not rescue this one. Put next first and the pointer takes offsets 0 through 7, data takes 8 through 11, and the total still rounds up to 16. A list of n such nodes therefore costs 16n bytes, of which 4n bytes are pure padding.
Every linked structure is built this way, including the nodes in binary trees and binary search trees. Each node stores its own data plus an address leading to the next separately allocated node.
GATE-style layout questions: nested structures and unions as members
Beyond a flat declaration, layout questions arrive in two shapes that cost marks: a structure nested inside another structure, and a union used as a member. Both are solved by computing the inner type first, then treating it as a single member with its own size and its own alignment.
struct P {
char a;
short b;
int c;
};
struct Q {
struct P p;
char x;
double y;
};Inside struct P: a takes offset 0; b needs alignment 2, so offset 1 is padding and b occupies 2 and 3; c needs alignment 4 and occupies 4 through 7. The widest alignment is 4 and 8 is already a multiple of 4, so the size is 8 bytes.
struct Q then treats p as one 8-byte member that must start at a multiple of 4. p occupies 0 through 7 and x takes offset 8. y needs alignment 8, so offsets 9 through 15 are seven padding bytes and y occupies 16 through 23. The widest alignment in Q is 8, and 24 is already a multiple of 8, so nothing is added at the end.
sizeof(struct P) = 8
sizeof(struct Q) = 24A union member is the second trap, because a union has an alignment of its own and its size is rounded up to that alignment:
union V {
int i;
char b[7];
};
struct S {
char t;
union V v;
};union V must hold its largest member, the 7-byte array, and must satisfy the strictest alignment among its members, which is 4 from int. Seven rounded up to a multiple of 4 is 8, so the union is 8 bytes, not 7. In struct S, t takes offset 0, v needs alignment 4, so offsets 1 through 3 are padding and v occupies 4 through 11. The total is 12 bytes.
Array questions reuse the same numbers. Ten elements of struct B occupy 160 bytes, because each element keeps its own 2 tail-padding bytes so that element 1 begins at offset 16, a multiple of 8.
sizeof(union V) = 8
sizeof(struct S) = 12
struct B arr[10] -> 10 * 16 = 160 bytesCommon structure and union traps
Adding member sizes without aligning each starting offset.
Forgetting to round a structure's final size to its widest alignment.
Treating a union's size as the sum rather than the suitably aligned largest member.
Assuming
#pragma pack(1)is a portable default. Packing directives are implementation-specific and may create slower or invalid unaligned accesses on some targets.Expecting bit-fields to have one universal bit layout. Their allocation details are implementation-defined.
Forgetting that a nested structure arrives with its own size and alignment.
Guessing offsets when the standard
offsetofmacro can report them for the current implementation.
The short version and next step
Place each structure member at an offset valid for that member, then round the total to the structure's widest required alignment. A union overlaps all members at offset 0, and its size is its largest member rounded up to its strictest alignment. A nested structure or union member arrives with a size and an alignment already fixed by its own layout, so compute the inner type first.
KnowledgeGate's question bank carries over 900 C-programming questions across layout and related topics. Start from Coding & Skills, work the examples in the C Programming course, and recompute every declaration above with the answers covered. If your offset table reaches 24 for A, 16 for B, 8 for U, 16 for Node, 8 for P, 24 for Q, 8 for V and 12 for S, the method is working.




