Day 1 of 5
⏱ ~60 minutes
C Programming in 5 Days — Day 1

C Fundamentals & Compilation

C is the language that built Unix, Linux, and most of the infrastructure the modern world runs on. It gives you direct memory control and near-hardware performance. Today you master the compilation pipeline, types, and the C mental model.

The Compilation Pipeline

C source goes through four stages: preprocessing (expand #include and #define macros), compilation (C source to assembly), assembly (assembly to object code .o files), and linking (combine object files and libraries into an executable). Run each stage separately: gcc -E (preprocess), gcc -S (compile to asm), gcc -c (assemble to .o), gcc (link). Understanding each stage helps debug subtle errors.

Types, Variables, and Operators

C has fixed-width types: char (1 byte), short (2), int (4), long (8 on 64-bit Linux), float (4), double (8). Use stdint.h for explicit sizes: uint8_t, int32_t, uint64_t. Operators: arithmetic (+,-,*,/,%), bitwise (&,|,^,~,<<,>>), comparison (==,!=,<,>), logical (&&,||,!), and the ternary (cond ? a : b). C has no boolean type by default — use stdbool.h for bool/true/false.

Control Flow

C control flow: if/else, while, do-while, for, switch/case, break, continue, goto (use sparingly). The for loop is idiomatic C: 'for (int i = 0; i < n; i++)'. Switch requires explicit break — fall-through is intentional but dangerous. goto is legitimate for error cleanup in system code (Linux kernel uses it extensively) but avoid it in application code.

c
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>

// Function prototype
bool is_prime(uint32_t n);

int main(void) {
    // Print primes up to 50
    for (uint32_t i = 2; i <= 50; i++) {
        if (is_prime(i)) {
            printf("%u ", i);
        }
    }
    printf("\n");
    return 0;
}

bool is_prime(uint32_t n) {
    if (n < 2) return false;
    if (n == 2) return true;
    if (n % 2 == 0) return false;
    for (uint32_t i = 3; (uint64_t)i * i <= n; i += 2) {
        if (n % i == 0) return false;
    }
    return true;
}

// Compile: gcc -Wall -Wextra -std=c11 -O2 primes.c -o primes
💡
Always compile with -Wall -Wextra -Werror. These flags turn on all warnings and treat them as errors. C's type system allows many dangerous implicit conversions that warnings catch before they become runtime bugs.
📝 Day 1 Exercise
Build a Calculator
  1. Write a C program that reads two integers and an operator (+,-,*,/) from stdin
  2. Use scanf() for input and printf() for output
  3. Handle division by zero: print an error message and return 1 from main
  4. Compile with: gcc -Wall -Wextra -std=c11 calc.c -o calc
  5. Test all operators and the division-by-zero case

Day 1 Summary

  • C compiles in four stages: preprocess, compile, assemble, link
  • Use stdint.h for explicit-width types: uint8_t, int32_t, uint64_t
  • Always compile with -Wall -Wextra -Werror to catch type errors early
  • Switch requires explicit break; fall-through is deliberate but error-prone
  • C has no built-in bool — use stdbool.h
Challenge

Implement the Sieve of Eratosthenes in C to find all primes up to 10,000,000. Measure runtime with clock(). Optimize memory: use a bit array instead of a bool array to reduce memory from 10MB to 1.25MB.

Finished this lesson?