Structures, Unions and File IO in C for GATE CS | EngineeringHulk


Structures, Unions & File I/O in C for GATE CS

Struct memory layout, padding rules, union sizing, bit fields, and file operations — with GATE-level sizeof questions and output tracing.

Last updated: April 2026  |  GATE CS 2024–2026 syllabus

Key Takeaways for GATE

  • struct: separate storage for each member. sizeof(struct) ≥ sum of members due to padding.
  • Padding rule: each member aligned to offset that is a multiple of its size. Struct ends padded to multiple of largest member’s size.
  • union: all members share same memory. sizeof(union) = sizeof(largest member) + alignment padding.
  • Bit fields: unsigned int x : 3 uses only 3 bits. Cannot take address of bit field.
  • typedef: creates alias — typedef struct Node Node; — allows using just Node instead of struct Node.
  • File I/O: fopen/fclose, text mode (fprintf/fscanf) vs binary mode (fread/fwrite).

1. Struct Basics

struct Point {
    int x;       // 4 bytes
    int y;       // 4 bytes
};               // sizeof(struct Point) = 8

struct Point p = {3, 4};
p.x = 10;              // member access with dot
struct Point *pp = &p;
pp->y = 20;            // member access via pointer with arrow

Accessing members:
Value: p.member   Pointer: pp->member(*pp).member

2. Structure Padding & Alignment

Alignment rule: Member of type T must be at an offset that is a multiple of sizeof(T).
Trailing padding: Struct size rounded up to multiple of alignment of largest member.

Example 1:

struct A {
    char  c;    // 1 byte at offset 0
    // 3 bytes padding (to align int to offset 4)
    int   i;    // 4 bytes at offset 4
    char  d;    // 1 byte at offset 8
    // 3 bytes trailing padding (to make size multiple of 4)
};
// sizeof(struct A) = 12 (not 6!)

Example 2 — Reordered (smaller):

struct B {
    int   i;    // 4 bytes at offset 0
    char  c;    // 1 byte at offset 4
    char  d;    // 1 byte at offset 5
    // 2 bytes trailing padding
};
// sizeof(struct B) = 8

Rule of thumb: Declare members in decreasing order of size to minimise padding.

Member orderMemberssizeof
char, int, char1+3pad+4+1+3pad12
int, char, char4+1+1+2pad8
double, char, int8+1+3pad+416
char, char, int, double1+1+2pad+4+816

3. Union

All members share the same memory starting at offset 0.
sizeof(union) = sizeof(largest member) + any trailing alignment padding.

union Data {
    int   i;     // 4 bytes
    float f;     // 4 bytes
    char  c[8];  // 8 bytes  ← largest
};
// sizeof(union Data) = 8

Writing to one member and reading another is type-punning — valid in C (undefined in C++).

Use cases: Memory-efficient variant types, type punning (reading float bits as int), protocol parsing.

4. Struct vs Union

Propertystructunion
Member storageSeparate for each memberShared (same location)
sizeof≥ sum of members (with padding)= largest member (with padding)
Valid members at onceAllOnly 1 (most recently written)
Use caseGroup related dataMemory-efficient variants

5. Bit Fields

struct Flags {
    unsigned int read  : 1;   // 1 bit
    unsigned int write : 1;   // 1 bit
    unsigned int exec  : 1;   // 1 bit
    unsigned int       : 5;   // 5 bits padding (unnamed)
};
// Packed into 1 byte (8 bits total)

Rules:
• Can only use int, unsigned int, or _Bool as base type (in standard C).
• Cannot take address of bit field (&f.read is illegal).
• Unnamed bit field of size 0 forces next field to start at the next unit boundary.
• Bit field order within a unit is implementation-defined (endianness-dependent).

6. typedef

typedef existing_type new_name; — creates type alias, not a new type.

typedef unsigned long long ULL;
typedef struct Node {
    int data;
    struct Node *next;   // must use 'struct Node' here, not 'Node' (not yet defined)
} Node;                  // now 'Node' is alias for 'struct Node'

Node n1;  // equivalent to: struct Node n1;

Common uses: simplifying function pointer declarations, struct aliases, platform-specific type abstraction (e.g., int32_t in <stdint.h>).

7. Nested Structs & Self-referential Structs

Nested struct:

struct Address { char city[20]; int pin; };
struct Person {
    char name[30];
    struct Address addr;   // embedded (not pointer)
};
// sizeof(Person) = 30 + sizeof(Address) + padding

Self-referential (linked list node):

struct Node {
    int data;
    struct Node *next;   // pointer to same type — OK (pointer is fixed size)
    // struct Node next; // ILLEGAL — incomplete type, infinite size
};

A struct cannot contain itself as a member (infinite size), but can contain a pointer to itself.

8. File I/O in C

FunctionPurposeMode
fopen(name, mode)Open file, returns FILE*“r”,”w”,”a”,”rb”,”wb”
fclose(fp)Close file, flush buffers
fprintf(fp, fmt, ...)Formatted write to fileText
fscanf(fp, fmt, ...)Formatted read from fileText
fgets(buf, n, fp)Read line (safer than gets)Text
fputs(str, fp)Write string to fileText
fread(buf, sz, n, fp)Read n items of size szBinary
fwrite(buf, sz, n, fp)Write n items of size szBinary
fseek(fp, off, whence)Move file position
ftell(fp)Get current file position
feof(fp)Test end-of-file flag
Standard streams: stdin, stdout, stderr (FILE* already open).
whence values for fseek: SEEK_SET (from start), SEEK_CUR (from current), SEEK_END (from end).
Always check fopen return: returns NULL on failure. Always fclose to flush buffers.

9. GATE Examples

GATE 2018 — What is sizeof(S)?

struct S {
    double d;   // 8 bytes, offset 0
    int    i;   // 4 bytes, offset 8
    char   c;   // 1 byte,  offset 12
                // 3 bytes trailing padding (to align to 8-byte boundary of double)
};

sizeof(S) = 8 + 4 + 1 + 3 = 16 bytes

GATE 2020 — What is sizeof(U)?

union U {
    int    a;   // 4 bytes
    double b;   // 8 bytes ← largest
    char   c;   // 1 byte
};

sizeof(U) = sizeof(double) = 8 bytes

GATE 2021 — Output question:

union { int i; char c[4]; } u;
u.i = 0x01020304;
printf("%x", u.c[0]);

On little-endian system: c[0] = least significant byte = 0x04. Output: 4
On big-endian: c[0] = 0x01. Endianness determines answer — GATE usually specifies.

10. Common Mistakes

  • Assuming sizeof(struct) = sum of members: Padding adds extra bytes. Always compute using alignment rules, or use __attribute__((packed)) to disable padding (non-standard).
  • Using union member after writing another: In C++, this is undefined behaviour. In C, it is implementation-defined. For GATE, assume the hardware stores in little-endian unless stated otherwise.
  • Self-referential struct with value, not pointer: struct Node { int data; struct Node next; } is illegal — incomplete type. Must use struct Node *next.
  • Forgetting fclose: Data may remain in the buffer and not be written to disk. Always fclose after writing, especially before reading the same file.
  • Using gets() instead of fgets(): gets() has no length limit and is a security vulnerability (buffer overflow). Always use fgets(buf, sizeof(buf), stdin).

11. FAQ

What is structure padding in C?
Padding is extra bytes inserted between struct members so each member starts at an address that is a multiple of its size (natural alignment). For example, a 4-byte int must start at an offset divisible by 4. Padding ensures correct and efficient CPU access on all architectures. Total sizeof(struct) includes all padding bytes.
What is the size of a union in C?
sizeof(union) equals the size of its largest member, plus any trailing padding needed for alignment. All members start at offset 0 and share the same memory. For union {int i; double d; char c[8];}: sizeof = 8 (double is largest, char[8] is same size).
What is the difference between struct and union?
struct allocates separate memory for each member sequentially (with padding), so all members are valid simultaneously. union allocates a single block shared by all members — the size equals the largest member — and only one member can hold a valid value at a time. struct is for grouping related data; union is for memory-efficient variant types.
What is the difference between fread and fscanf?
fread(buf, size, n, fp) reads n raw binary items of given size into buf — no formatting or whitespace interpretation. fscanf(fp, fmt, …) reads formatted text from file using a format string like scanf. Use fread/fwrite for binary files (images, structs); use fprintf/fscanf for human-readable text files.