3B Infrastructure home

All subjects

Engineering Computing (C)

Programming close to the machine with C: how code becomes a program, how memory really works, and why pointers matter. Press play on any sketch to watch it happen.

1 From source code to a program

C is compiled. A set of tools turns your text file into machine code the processor can run directly, which is why C is fast and why it dominates embedded work.

  • Preprocessor: pastes in #include files and expands #define macros.
  • Compiler: checks your code and translates it to assembly.
  • Assembler: turns assembly into an object file of machine code.
  • Linker: joins your object files and libraries into one executable.
#include <stdio.h>

int main(void) {
    printf("Hello, engineer!\n");
    return 0;
}

gcc -Wall -Wextra hello.c -o hello
./hello

Pipeline diagram

hello.cPreprocessorCompilerAssemblerLinkerhello

1/5 The preprocessor pastes stdio.h into your file.

Rule of thumb: Always compile with -Wall -Wextra. Warnings are bugs that the compiler caught for free.

2 Memory and pointers

Every variable lives at an address in memory. A pointer is a variable that stores one of those addresses. This lets a function change a caller's data, and it lets C talk directly to hardware.

  • &: the address of a variable.
  • *: follow a pointer to the value it points at.
  • Pass by pointer: C copies arguments, so pass an address to change the original.
  • NULL: a pointer to nothing. Following it crashes the program.
int a = 5;
int *p = &a;   // p holds a's address
*p = 9;        // a is now 9

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

Memory diagram

p(empty)a at 0x100value 5

1/4 int a = 5 puts the value 5 at some address, say 0x100.

Rule of thumb: Draw boxes and arrows on paper. Pointers get far easier once you can see them.

3 Arrays, the heap and memory bugs

C trusts you completely. It does not check array bounds or free memory for you, so a small mistake can corrupt your data silently. Knowing the common bugs is half of writing safe C.

  • Stack: automatic local variables, gone when the function returns.
  • Heap: memory you ask for with malloc and must release with free.
  • Buffer overflow: writing past the end of an array and corrupting whatever is next.
  • Memory leak: forgetting to free, so usage grows until the program dies.
  • Use after free: using memory after you gave it back.
char name[4];
strcpy(name, "Alexander");   // overflow!

snprintf(name, sizeof name, "%s", "Alexander");   // safe: cut to "Ale"

Memory diagram

name[4]emptyisAdmin0Input: "Alexander"

1/5 Two variables sit side by side in memory. The array has room for 4 bytes.

Rule of thumb: Run your programs under Valgrind or with -fsanitize=address to catch these bugs while testing.