C Programming Fundamentals: Complete Guide with Worked Examples for GATE and Placements

Build a reliable C foundation through traced outputs, pointer arithmetic, function calls, arrays, structures, recursion, and memory allocation.

KnowledgeGate Team

Exam prep & CS education

Updated 13 Aug 20267 min read

C looks small, yet students often lose accessible marks on its short output questions. GATE uses pointers, precedence, and integer promotion to test whether you can trace code precisely, while placement interviews ask you to apply the same ideas to swaps, strings, and memory bugs. The rules that settle those traces are few: how wide each type is, when a conversion happens, which operator binds first, and what a pointer's arithmetic steps over.

Every size here follows the GATE convention: char is 1 byte, int and float are 4 bytes, double is 8 bytes, and a pointer is 4 bytes on a 32-bit build or 8 bytes on a 64-bit build.

The building blocks: data types, sizes, and format specifiers

C's core types describe both the kind of value and its storage. With printf, use %d for int, %c for char, %f for floating-point values, %u for unsigned int, and %zu for the size_t value returned by sizeof.

Consider this array:

char s[] = "GATE";
printf("%zu %zu", sizeof(int), sizeof(s));

It prints 4 5. The first value follows the assumed 4-byte int. The second is 5 because the array stores G, A, T, E, and the terminating \0.

Now take signed char c = 200;. Under the assumed 8-bit two's-complement representation, 200 is 11001000. Interpreted as signed, its value is 200 - 256 = -56, so printf("%d", c); prints -56. An unsigned char stores and prints 200 instead.

Operators, precedence, and conversion traps

Multiplication and division bind more tightly than addition and subtraction. Therefore:

printf("%d", 1 + 2 * 3 - 4 / 2);

First, 2 * 3 = 6 and 4 / 2 = 2. The remaining expression is 1 + 6 - 2 = 5, so the output is 5.

Type conversion creates a less visible trap:

int a = 7, b = 2;
float r = a / b;

Both operands are integers, so C computes 7 / 2 = 3 before assigning the result to float. Thus r becomes 3.0, not 3.5. Writing float r = (float)a / b; changes one operand before division, so the calculation becomes 7.0 / 2 = 3.5.

Never write expressions such as i++ + ++i. Their behaviour is undefined because the same object is modified more than once without the required sequencing, so no traced output is trustworthy.

Control flow: loops, conditionals, and switch

C's control constructs are if, else, switch, while, do-while, and for. A do-while body always runs at least once because its test comes after the body, while a while test can reject the body immediately. A switch case label is an entry point, so execution continues into the following case unless a break stops it.

Loop questions reward a trace:

int i, s = 0;
for (i = 1; i <= 5; i++) {
    if (i % 2 == 0) continue;
    s += i;
}
printf("%d %d", s, i);

The continue skips the body when i is 2 and 4, so s accumulates 1 + 3 + 5 = 9. The loop ends when the test fails at i = 6, and i keeps that value because it was declared outside the loop. The output is 9 6; answering 9 5 means the final increment was forgotten. Loops in C: for, while and do-while takes each loop form through its own traces, including nested loops.

Pointers, the heart of C

A pointer stores an address. The & operator takes an address, while * follows an address to access its object. The identity behind many C and data-structure questions is arr[i] == *(arr + i).

int a[5] = {10, 20, 30, 40, 50};
int *p = a;

Here, *(p + 2) is 30, and *(a + 3) is 40. Suppose a[0] begins at address 2000. Because an int occupies 4 bytes, p + 2 points to 2000 + 2 * 4 = 2008, the address of a[2]. Pointer arithmetic moves in units of the pointed-to type, not single bytes. C Pointer Basics MCQs pushes the same rule through double and dangling pointers.

An array of five integers in memory, where p + 2 points to the element holding 30 at address 2008.

Functions, scope, and storage classes

C passes arguments by value, so a function normally receives copies. To change variables owned by the caller, pass their addresses:

void swap(int *x, int *y) {
    int t = *x;
    *x = *y;
    *y = t;
}

int a = 5, b = 8;
swap(&a, &b);

The temporary saves 5, *x = *y makes a = 8, and *y = t makes b = 5. A version with plain int x, int y parameters would swap only local copies, leaving the caller's values unchanged.

A static local solves a different problem:

void f(void) {
    static int c = 0;
    c++;
    printf("%d ", c);
}

Three calls print 1 2 3 because c is initialised once and retains its value. A plain automatic local initialised to zero on every call would print 1 1 1. Scope and lifetime are separate: c is visible only inside f, but its lifetime runs for the whole program. The four storage classes are auto, static, extern, and register. extern names an object defined elsewhere, while register is only a hint the compiler may ignore, which is why a register variable has no address to take. Storage Classes in C carries the full scope and lifetime table.

Arrays, strings, and structures

A C string is a character array ending in \0. For char s[] = "GATE", strlen(s) is 4, which counts visible characters, while sizeof(s) is 5, which counts the complete array including its terminator.

Alignment affects structure size:

struct S {
    char c;
    int x;
};

When int needs 4-byte alignment, c occupies byte 0, bytes 1 to 3 are padding, and x occupies bytes 4 to 7. Therefore sizeof(struct S) is 8, not 5.

A union overlays its members in the same memory, so its size must accommodate its largest member. A typedef only gives a type another name. Arrays provide no bounds checking: accessing a[5] in a five-element array is undefined behaviour. Arrays and Strings in C covers array-to-pointer decay and 2D address arithmetic.

Recursion and dynamic memory

Recursion becomes manageable when every call is expanded:

int fact(int n) {
    return n <= 1 ? 1 : n * fact(n - 1);
}

For fact(4), the trace is 4 * fact(3) = 4 * 3 * fact(2) = 4 * 3 * 2 * fact(1) = 4 * 3 * 2 * 1 = 24. At the deepest point, the call stack contains four frames: fact(4), fact(3), fact(2), and fact(1).

Dynamic allocation uses the heap:

int *arr = malloc(5 * sizeof(int));

Under the stated convention, this reserves 5 * 4 = 20 bytes. Check that allocation succeeded, use the block, and pair it with free(arr);. Ordinary local variables disappear when their function returns, while allocated heap memory remains until it is freed. Dynamic Memory Allocation in C compares malloc, calloc, and realloc, and lists the bugs exams test.

A C process memory layout with the heap growing upward and the stack growing downward toward each other.

The traps that quietly cost marks

Small syntax differences often produce large errors:

  • if (x = 5) assigns 5 to x, and the condition is true. Use if (x == 5) to compare.

  • An uninitialised pointer does not point to a valid object. Using a pointer after free() is also undefined behaviour. Set a freed pointer to NULL when that helps prevent accidental reuse.

  • char buf[4] cannot hold "GATE" because the string needs five slots including \0. This is the same strlen 4 versus sizeof 5 distinction seen earlier.

  • Integer division produced 3.0 instead of 3.5, while the 8-bit signed conversion produced -56 instead of 200. Both mistakes come from ignoring the type used for an operation.

How GATE and placements test C, and where to go next

The official GATE Computer Science syllabus places C under Programming and Data Structures. Confirm the current wording on the organizing institute's official GATE test papers and syllabus page. Questions commonly ask you to predict a 1-mark or 2-mark result involving pointer arithmetic, arr[i], precedence, integer conversion, structure padding, or recursion.

Use GATE CS Subject Weightage to place C inside the wider subject plan. Pointers lead naturally to Binary Trees and Binary Search Trees, while array reasoning continues in Sorting Algorithms: Complexity and Comparison.

Placement interviews turn the same foundation into live tasks: swap two values by reference, reverse a string in place, find a memory leak, or reverse a linked list. Coding and DSA Courses for Placements is the interview-drills path once the language rules are secure.

The short version and next step

Master pointers, precedence, and integer conversion first because they unlock the fastest tracing questions, then move into data structures. The C Programming Course provides the full concept sequence with worked MCQs when you want one structured path instead of piecing the topic together.