Introduction

A structure groups values of different types into one object, such as a student record with a name and marks, or a list node with a key and a pointer to the next node. A union lets several members share the same storage, so that the object holds one of them at a time. An enumeration gives names to a set of integer constants.

Structures are the building blocks of every linked data structure in this subject: linked lists, trees, and graph adjacency lists. The usual points of care are member access through pointers, copying semantics, and the size of a structure once padding is taken into account.

Conventions: C11, gcc on x86-64 Linux. On this platform each basic type is aligned to its own size (char 1, short 2, int 4, long, double and pointers 8), as reported by _Alignof. All sizes and offsets below depend on this alignment assumption; a question that states another one must be solved with its rule.

Prerequisites

Core concepts

Declaring and using structures

C
struct point { int x, y; };                    /* structure tag: point */
struct point p = {3, 4};                       /* positional initialiser */
struct point q = { .y = 9 };                   /* designated (C99): q.x is 0 */
typedef struct node { int key; struct node *next; } Node;   /* alias Node */
  • Members are accessed with . on a structure and with -> on a pointer to a structure: ptr->key means (*ptr).key. The parentheses matter, because . binds tighter than unary *: *ptr.key means *(ptr.key).
  • Members not mentioned in an initialiser are set to zero.
  • Assignment copies every member: after struct point r = p; r.x = 100;, p.x is still 3. Structures can be passed to and returned from functions by value (a full copy) (Functions and Parameter Passing).
  • Structures cannot be compared with ==; compare member by member. (memcmp is unreliable because of padding bytes.)
  • A structure cannot contain a member of its own type (that would be infinitely large), but it can contain a pointer to its own type. Such a self-referential structure is how linked nodes are built.
  • typedef creates an alias, not a new type: Node and struct node are the same type.

Alignment and padding

Many processors access an object fastest, or only, when its address is a multiple of its alignment. The compiler therefore inserts unused padding bytes inside and at the end of a structure. Under the stated alignment assumption the rules are:

  1. Members are laid out in declaration order (the compiler may not reorder them).
  2. Each member starts at the next offset that is a multiple of its alignment. The first member is at offset 0.
  3. The structure's alignment is the largest alignment of its members, and its size is rounded up to a multiple of that alignment, so that every element of an array of structures is aligned.
Layout of struct A with padding
Figure 1. Byte layout of struct { char c; int i; char d; } (12 bytes: 3 padding bytes after c, 3 at the end) beside the reordered struct { int i; char c; char d; } (8 bytes), assuming each type is aligned to its size.

Unions

C
union U { int i; char c[6]; };
union Bytes { unsigned i; unsigned char b[4]; };
union Pun { int i; float f; };
  • All members start at offset 0 and overlap. The size is at least the size of the largest member, rounded up to the union's alignment: sizeof(union U) is 8 (6 rounded up to a multiple of 4).
  • Storing into one member and then reading another reinterprets the stored bytes as the other type (C11 footnote 95). The result depends on the representation, for example byte order. On little-endian x86-64, after u.i = 0x01020304 with union Bytes u, the byte u.b[0] is 4 and u.b[3] is 1. With union Pun p and p.f = 1.0f, reading p.i gives the bit pattern 0x3f800000. Reading a different scalar member can encounter a trap representation and then has undefined behaviour; representation-dependent type punning does not guarantee a valid scalar value. Character-byte inspection is a distinct operation that can inspect object representation. The printed x86-64 results require the stated member sizes, byte order and valid representations; they are implementation examples, not universal C outputs.
  • Typical uses: saving memory when only one field is meaningful at a time (usually with a separate "tag" field saying which), and inspecting representations.

Enumerations

C
enum colour { RED, GREEN = 5, BLUE, CYAN = 2, MAGENTA };
  • Enumerators are integer constants of type int. The first defaults to 0; each later one without an explicit value is one more than the previous one. So RED is 0, GREEN 5, BLUE 6, CYAN 2 and MAGENTA 3. Values may repeat.
  • An enum variable has an implementation-defined integer type able to hold all the values (4 bytes with gcc here). C does not restrict an enum variable to the listed values.
  • Enumerators are often used as case labels and array sizes, because they are constant expressions.

Bit-fields (brief)

A member can be declared with a width in bits: struct flags { unsigned a : 1; unsigned b : 3; unsigned c : 4; };. Storing a value too large for an unsigned bit-field keeps only the low bits: assigning 9 to the 3-bit field b stores 9 mod 8=19 \bmod 8 = 1. The layout of bit-fields within storage units is implementation-defined; with gcc this structure occupies 4 bytes. Bit-fields have no address, so &fl.b is invalid.

How it works: computing `sizeof` of a structure

Apply the three rules member by member, tracking the current offset.

StructureOffsets of membersPaddingsizeof
struct A { char c; int i; char d; }c 0, i 4, d 83 after c, 3 at end12
struct B { int i; char c; char d; }i 0, c 4, d 52 at end8
struct C { char c; double d; int i; }c 0, d 8, i 167 after c, 4 at end24
struct D { double d; int i; char c; }d 0, i 8, c 123 at end16
struct E { char a, b, c; }0, 1, 2none3

Ordering members from largest to smallest alignment minimises padding: struct C and struct D hold the same members, yet one is 24 bytes and the other 16. The minimum possible size is the sum of the member sizes rounded up to the largest alignment.

Worked examples

All outputs below are for C11 with gcc on x86-64 Linux (LP64).

Example 1 (copy semantics).

C
struct student { char name[8]; int marks; };
void bump(struct student s)    { s.marks += 10; }   /* changes a copy */
void bump_p(struct student *s) { s->marks += 10; }  /* changes the original */

struct student s = {"Asha", 70};
bump(s);    /* s.marks is still 70 */
bump_p(&s); /* s.marks is now 80 */

Example 2 (array of structures and ->). struct student arr[2] = {{"Ravi", 50}, {"Meena", 60}}; struct student *sp = arr; sp++; Then sp->name is "Meena", (sp - 1)->marks is 50, and sizeof arr is 24 (each element is 12 bytes: 8 for the name and 4 for marks, already aligned).

Example 3 (self-referential nodes). Node n2 = {20, NULL}, n1 = {10, &n2}; Node *h = &n1; gives h->key 10, h->next->key 20, and h->next->next == NULL is 1.

Example 4 (enumeration values). For enum colour above, printf("%d %d %d %d %d", RED, GREEN, BLUE, CYAN, MAGENTA) prints 0 5 6 2 3.

Important properties and observations

  • p->m is (*p).m; *p.m is a different expression.
  • Structure assignment and parameter passing copy all members, including arrays inside the structure.
  • Structures cannot be compared with ==.
  • Padding depends on alignment rules; the size of a structure is at least the sum of its members and is a multiple of its alignment.
  • A union's size is its largest member rounded up to its alignment; only one member holds a meaningful value at a time.
  • Enumerators are int constants that count up from the previous value.
  • A structure may contain a pointer to its own type but not an instance of it.

GATE examination perspective

  • sizeof of a structure or union: state the alignment assumption, then apply the offset rules; reorder members if the question asks for the minimum size.
  • Pointer access chains: p->next->next->key; draw the nodes.
  • Copy versus pointer semantics when a structure is passed to a function.
  • Enum values with some explicit initialisers.
  • Union reads after writing another member: the answer depends on endianness, which the question must state.

Summary

Sources

  1. ISO/IEC 9899:2011 (C11), committee draft N1570, (consulted 2026-11-09), Section 6.2.8 (alignment of objects), 6.5.2.3 (structure and union members, footnote 95 on reading a different union member), 6.7.2.1 (structure and union specifiers, padding and bit-fields), 6.7.2.2 (enumeration specifiers), 6.7.9 (initialization).
  2. B. W. Kernighan and D. M. Ritchie, The C Programming Language, 2nd ed., Prentice Hall, 1988: Chapter 6 (structures, including 6.8 unions and 6.9 bit-fields) and Section 2.3 (enumeration constants).

Next steps