Storage Classes, Structures and Enums in C: Worked Examples for GATE Output and sizeof Questions

Trace static variables across calls, calculate structure padding byte by byte, compare structures with unions, and follow enum values after an explicit jump.

KnowledgeGate Team

Exam prep & CS education

Updated 21 Aug 20265 min read

Students memorise static, struct and enum, then lose marks when a short C program asks for output or an exact sizeof. These topics are tested mainly through output prediction and byte counting, not definitions. Three question types carry almost all of those marks: predicting output when a static local survives across calls, computing sizeof once alignment inserts padding, and reading an enum value after an explicit jump. If you are still mapping the whole syllabus, the GATE CS 6-month plan shows where C programming sits in it.

What a storage class controls

Every storage class controls scope, lifetime, linkage and default value: where a name is visible, how long its memory lives, whether another file can refer to it, and its uninitialised value.

Class

Keyword

Scope

Lifetime

Default value

Linkage / storage

auto

auto (default for locals)

block

one function call

garbage / indeterminate

stack

register

register

block

one function call

garbage / indeterminate

CPU register hint; its address cannot be taken

static (local)

static

block

whole program

0

data segment, initialised once

static (global)

static

whole file

whole program

0

data segment, internal linkage

extern

extern

file or block where declared

whole program

0

data segment, external linkage

Static and global variables default to 0. Uninitialised auto and register locals have indeterminate values.

The static-variable trap, worked line by line

Consider one static local and one automatic local inside the same function:

#include <stdio.h>
void counter() {
    static int c = 0;   // initialised ONCE, survives every call
    int a = 0;          // auto: created fresh on each call
    c++; a++;
    printf("%d %d\n", c, a);
}
int main() {
    counter();
    counter();
    counter();
    return 0;
}

Trace the calls:

  • Call 1: c goes 0 to 1; a goes 0 to 1. Output: 1 1.

  • Call 2: c keeps 1 and becomes 2; fresh a becomes 1. Output: 2 1.

  • Call 3: c keeps 2 and becomes 3; fresh a becomes 1. Output: 3 1.

The final output is:

1 1
2 1
3 1

The static initialiser runs once. The automatic variable is rebuilt for every call.

extern and linkage: declaration versus definition

extern int x; declares that x exists elsewhere; int x = 5; defines it and allocates storage. An initialised extern int x = 5; is also a definition, so repeating it across files can cause a multiple-definition linker error.

A global static name has internal linkage and is private to its source file. Two files may therefore have separate static int count; objects.

Taking &r for a register variable is a compile-time error. Drop register if its address is needed.

Structures and the padding rule that changes sizeof

Every sizeof figure here assumes a typical 64-bit build with 4-byte int alignment and 8-byte double alignment.

struct Student {      // members in this order
    char grade;       // offset 0        (1 byte)
    int  roll;        // offsets 4..7    (needs 4-byte alignment)
    char section;     // offset 8        (1 byte)
};                    // sizeof = 12

grade is at 0. To align roll, offsets 1 to 3 are padding and roll takes 4 to 7. section is at 8. Tail padding at 9 to 11 rounds the total to a multiple of 4. Thus sizeof(struct Student) is 12 bytes, not 1 + 4 + 1 = 6.

Now place the largest field first:

struct StudentPacked {
    int  roll;        // offsets 0..3
    char grade;       // offset 4
    char section;     // offset 5
};                    // sizeof = 8

roll takes 0 to 3, grade takes 4, and section takes 5. Padding at 6 and 7 makes 8 bytes. Reordering saves 12 - 8 = 4 bytes.

A self-referential struct node { int data; struct node *next; }; stores a pointer to its own type, the basis of linked-list nodes. Practise that connection in Data Structures MCQs. typedef struct { ... } Student; only shortens the type name; it does not alter layout.

Byte layout of struct Student padded to 12 bytes beside the reordered StudentPacked at 8 bytes.

Unions share one slot

The same three members occupy very different amounts of memory in a union and in a structure:

union Value {         // all members overlap at offset 0
    char   c;         // uses byte 0
    int    i;         // uses bytes 0..3
    double d;         // uses bytes 0..7
};                    // sizeof = 8 (largest member)

struct Bundle {       // same three members, laid end to end
    char   c;         // offset 0
    int    i;         // offsets 4..7 (3 bytes padding after c)
    double d;         // offsets 8..15 (8-byte aligned)
};                    // sizeof = 16

Every union member starts at 0, so the union needs one slot for its largest member. The double needs 8 bytes, hence sizeof(union Value) = 8. Writing i overwrites bytes seen by c and d; only one member is meaningfully active at a time.

Structure members do not overlap: c 1 + padding 3 + i 4 + d 8 = 16 bytes. The contrast is union 8, structure 16.

Memory layout of struct Bundle at 16 bytes beside union Value overlapping its members in one 8-byte slot.

Enums and the auto-increment trap

enum Weekday { MON, TUE, WED, THU = 10, FRI, SAT, SUN };

Enumeration starts at 0 unless specified: MON = 0, TUE = 1, WED = 2, THU = 10. Counting resumes there, giving FRI = 11, SAT = 12, SUN = 13. printf("%d", FRI); prints 11, not 4.

An enum constant is a named integer constant. sizeof(enum Weekday) is typically 4 bytes, like int. Enums clarify states and flags but are not a new range-checked C type.

The traps GATE deliberately sets

  • Auto local assumed to be 0: it is indeterminate. Initialise it.

  • Structure size treated as a sum: alignment inserts padding. Count offsets; Student is 12, not 6.

  • Union sized like a structure: union members overlap. Use the largest member, 8 here, not the structure's 16.

  • Address taken for a register variable: &r fails to compile. Remove register.

  • Static local reset each call: it initialises once. Carry its value across calls.

  • Initialised extern treated as a declaration: extern int x = 5; is a definition. Declare with extern, define once elsewhere.

  • Enum restarted after a jump: count from the last explicit value. THU = 10 makes FRI = 11.

How GATE and interviews test this

C programming sits under Programming and Data Structures in the GATE CS syllabus. The organising IIT publishes the current topic list on the official GATE portal, along with the marks split and the sectional rules for the cycle. To see how C weighs against other subjects when you budget revision hours, use GATE CS Subject Weightage.

Expect output prediction with static storage, numerical sizeof with padding or overlap, and one-line MCQs on linkage, register addresses or enums. Interviews ask the same padding and overlap reasoning aloud.

The short version and next step

Storage class means scope, lifetime, linkage and default value. Static locals persist; automatic locals are indeterminate unless initialised. Structures include padding, unions follow their largest member, and enums continue from the latest explicit value.

Practise output prediction and byte-counting drills in the C Programming Course. When you are ready to place C beside the rest of the syllabus, the GATE CS Exam Preparation category collects the subject-by-subject guides.