Active Recall
•
Semester 01 Curriculum Scope
SPC C Programming Flashcards
Master core concepts, plain-English intuition, exact theorems, and high-probability exam traps across LAC, SPC, FCS, and IWT.
SPC C Programming Flashcards
How is a C program laid out in memory during execution?
💡 Intuition: Memory is split into 4 segments to balance execution speed, dynamic growth, and memory safety.
📐 Core Rule: 1. Text Segment: Read-only machine code.
2. Data/BSS: Initialized (Data) & uninitialized (BSS=0) globals and statics.
3. Heap: Dynamic memory managed via malloc/free (grows upward).
4. Stack: Local variables, function frames, return addresses (grows downward).
🎯 Exam Cue: Local variables live on stack; dynamically allocated memory lives on heap.
What is the hierarchy of operator precedence in C, and how does short-circuit evaluation work?
💡 Intuition: Controls evaluation order when parentheses are absent.
📐 Core Rule: Postfix (`() [] ++ --`) $\to$ Unary (`* & ! sizeof`) $\to$ Arithmetic (`* / %` then `+ -`) $\to$ Relational (`< >` then `== !=`) $\to$ Bitwise $\to$ Logical (`&&` then `||`) $\to$ Ternary (`?:`) $\to$ Assignment (`=`).
🎯 Exam Cue: Short-circuit: In `A && B`, if `A` is false, `B` is never evaluated! In `A || B`, if `A` is true, `B` is skipped.
What is the exact difference between `*p++`, `(*p)++`, `*(++p)`, and `++*p`?
💡 Intuition: Postfix `++` has higher precedence than unary dereference `*`.
📐 Core Rule: 1. `*p++`: Dereference current `p`, then increment pointer address `p`.
2. `(*p)++`: Dereference `p`, then increment the stored value.
3. `*(++p)`: Increment pointer address first, then dereference new address.
4. `++*p`: Dereference `p`, then prefix-increment the stored value.
🎯 Exam Cue: High-frequency output tracing question in CAT exams.
In C, how are arrays and pointers related, and what are their crucial differences?
💡 Intuition: Array name `a` decays to a pointer to its first element `&a[0]` in expressions, so `a[i] == *(a + i)`.
📐 Core Rule: Differences:
1. Array name is not a modifiable l-value (`a = ptr` is illegal; `ptr = a` is legal).
2. `sizeof(arr)` gives total bytes of all elements; `sizeof(ptr)` gives 4 or 8 bytes.
3. `&arr` has type pointer-to-array `int (*)[N]`; `arr` decays to `int *`.
🎯 Exam Cue: `i[a]` is valid in C because `*(i + a) == *(a + i) == a[i]`.
Compare the 4 storage classes in C (`auto`, `register`, `static`, `extern`) across Scope, Lifetime, and Default Value.
💡 Intuition: Dictates where a variable lives, when it is destroyed, and which functions can access it.
📐 Core Rule: 1. `auto`: Block scope, function lifetime (stack), garbage default.
2. `register`: Block scope, CPU register, no address `&` operator, garbage default.
3. `static`: Retains value between calls! Local/file scope, program lifetime, default `0`.
4. `extern`: Global scope across files, program lifetime, default `0`.
🎯 Exam Cue: A `static` local variable is initialized only once, before program start.
Contrast `malloc()`, `calloc()`, `realloc()`, and `free()` across arguments, initialization, and failure behavior.
💡 Intuition: Allocates and resizes memory at runtime on the heap.
📐 Core Rule: 1. `malloc(size)`: 1 argument; allocated memory contains garbage values.
2. `calloc(num, size)`: 2 arguments; initializes all allocated bytes to zero.
3. `realloc(ptr, new_size)`: Resizes block; preserves existing content; returns new address.
4. `free(ptr)`: Releases heap block. Always set `ptr = NULL` immediately!
🎯 Exam Cue: All return `void *` (or `NULL` on failure). Always check `if (ptr == NULL)`.
Does C have true pass-by-reference? How do you modify a caller's variable inside a function?
💡 Intuition: C is strictly pass-by-value only. To modify a caller's variable, you must pass the variable's address (pointer) by value.
📐 Core Rule: Caller: `swap(&x, &y);` (passes memory addresses).
Function: `void swap(int *a, int *b) { int t = *a; *a = *b; *b = t; }` (dereferences pointers to alter original memory).
🎯 Exam Cue: Passing an array automatically passes the address of its first element (`arr` decays to `&arr[0]`), so changes to elements persist in caller.
How are strings represented in C, and why is `gets()` strictly forbidden?
💡 Intuition: Strings are null-terminated character arrays (`'\0'`, ASCII 0).
📐 Core Rule: 1. Array size must be at least $\text{length} + 1$ to hold `'\0'`.
2. `gets()` does not check destination buffer bounds, causing stack buffer overflows (removed in C11).
3. Always use `fgets(str, sizeof(str), stdin)` for safe input.
🎯 Exam Cue: `sizeof("hello") == 6` (includes `\0`), but `strlen("hello") == 5`.
Compare `struct` and `union` in C. How do they allocate memory for members?
💡 Intuition: Structures allocate independent memory for every member; Unions share a single overlapping memory space.
📐 Core Rule: 1. `struct`: Size $\ge$ sum of member sizes (plus padding). All members coexist simultaneously.
2. `union`: Size = size of largest member (rounded to alignment). Only one member can hold a valid value at any time.
🎯 Exam Cue: Assigning to one member of a union overwrites all other members.
Why is `sizeof(struct { char a; int b; char c; })` equal to 12 bytes instead of 6 bytes on a 32/64-bit architecture?
💡 Intuition: Modern CPUs fetch memory in aligned word chunks (4 or 8 bytes) for hardware performance.
📐 Core Rule: 1. `char a` (1 byte) + 3 bytes padding so `int b` aligns at multiple of 4.
2. `int b` (4 bytes).
3. `char c` (1 byte) + 3 bytes trailing padding so total struct size is a multiple of largest member alignment (4).
Total: $1 + 3 + 4 + 1 + 3 = 12$ bytes.
🎯 Exam Cue: Reordering members to `struct { int b; char a; char c; }` reduces size to 8 bytes.
What are the differences between `"r"`, `"w"`, `"a"`, and `"r+"` file access modes in `fopen()`?
💡 Intuition: Dictates read/write permission, initial pointer position, and file creation behavior.
📐 Core Rule: 1. `"r"`: Read only; file must exist (returns NULL if missing).
2. `"w"`: Write only; creates file if missing; truncates/erases if exists!
3. `"a"`: Append; writes strictly to end of file; preserves existing content.
4. `"r+"`: Read and write; file must exist; pointer starts at beginning.
🎯 Exam Cue: Always verify `FILE *fp = fopen(...)` is not `NULL` before performing file operations.
How do you declare and invoke a function pointer in C, and why is it useful?
💡 Intuition: Stores the memory address of executable code, enabling callbacks and dynamic dispatch.
📐 Core Rule: Declaration: `int (*func_ptr)(int, int);` (parentheses around `*func_ptr` are mandatory).
Assignment: `func_ptr = add;`
Invocation: `int res = func_ptr(5, 3);`.
🎯 Exam Cue: Classic exam example is the custom comparator in `qsort()`: `int (*cmp)(const void *, const void *)`.
What are the differences and pitfalls of `#define SQUARE(x) (x * x)` vs an inline function?
💡 Intuition: Macros are raw text substitutions performed before compilation by preprocessor; they do not respect types or operator precedence.
📐 Core Rule: Pitfalls:
1. Without inner parentheses, `SQUARE(2 + 3)` expands to `2 + 3 * 2 + 3 = 11` (not 25)!
2. Double evaluation: `SQUARE(i++)` expands to `(i++) * (i++)`, incrementing `i` twice.
🎯 Exam Cue: Always wrap every macro argument in parentheses: `#define SQUARE(x) ((x) * (x))`.
Explain `int main(int argc, char *argv[])`. What is `argv[0]`, and how do you access the first user argument?
💡 Intuition: Allows passing parameters to a C program directly from the terminal prompt.
📐 Core Rule: 1. `argc`: Argument count (includes program name, so $\ge 1$).
2. `argv`: Array of string pointers (`char *`).
3. `argv[0]`: Program execution name/path.
4. `argv[1]`: First user argument.
5. `argv[argc]`: Guaranteed to be `NULL`.
🎯 Exam Cue: Convert string arguments to numbers using `atoi(argv[1])` or `strtol()`.
Differentiate between a Dangling Pointer, a Memory Leak, and a Wild Pointer.
💡 Intuition: The three classic pointer bugs that cause crashes and security vulnerabilities.
📐 Core Rule: 1. Dangling Pointer: Points to deallocated memory (e.g. after `free(p)` or returning address of local stack variable).
2. Memory Leak: Heap memory allocated via `malloc()` has no remaining pointers to it and was not freed.
3. Wild Pointer: An uninitialized pointer holding arbitrary garbage address (`int *p;`).
🎯 Exam Cue: Fix wild pointer by initializing `p = NULL`. Fix dangling pointer by setting `p = NULL` after `free`.
What are the two mandatory requirements of a recursive function, and what happens if the base case is missing?
💡 Intuition: A function that solves a problem by calling itself with smaller sub-problems.
📐 Core Rule: 1. Base Case: The termination condition that returns without recursing.
2. Recursive Step: Moves inputs closer toward the base case.
Missing base case $\implies$ infinite recursion $\to$ stack exhaustion crash (`Segmentation fault / Stack overflow`).
🎯 Exam Cue: Every recursive call allocates a new stack frame storing local variables and return address.
Browse SPC notes and course resources