Syntax and the compiled toolchain

How the preprocessor, compiler and linker turn a .c file into a program, and the core syntax you write in between.

From source to executable

C is compiled ahead of time. A single gcc hello.c -o hello hides four stages; running them separately is the fastest way to understand where errors come from.

gcc -E hello.c -o hello.i     # preprocess: #include and #define are expanded
gcc -S hello.i -o hello.s     # compile: C becomes assembly
gcc -c hello.s -o hello.o     # assemble: assembly becomes an object file
gcc hello.o -o hello          # link: objects plus libraries become an executable

# in practice, one command, with the warnings turned up
gcc -std=c17 -Wall -Wextra -Wpedantic -g -O2 hello.c -o hello
FlagWhat it does
-std=c17Choose the language revision (also c11, gnu17)
-Wall -WextraEnable the warnings you actually want; never build without them
-WerrorTreat warnings as errors so they cannot be ignored
-gEmit debug information for gdb and the sanitisers
-O0 / -O2No optimisation, best for debugging / normal release optimisation
-fsanitize=address,undefinedRuntime checks for memory errors and undefined behaviour
-cCompile to an object file and stop before linking
-I / -L / -lAdd an include directory, a library directory, or link a library

The core syntax

#include <stdio.h>      /* declarations of the standard I/O functions */
#include <stdlib.h>
#include <stdint.h>

#define MAX_ITEMS 16   /* a macro: textual substitution, with no type checking */

/* a declaration tells the compiler the function exists */
static int sum(const int *values, size_t n);

int main(void) {
    int32_t total = 0;
    double rate = 0.075;
    char grade = 'A';
    const char *name = "Ada";     /* pointer to read-only text */

    int values[MAX_ITEMS] = { 0 };
    for (size_t i = 0; i < MAX_ITEMS; i++) {
        values[i] = (int)i * 2;
    }

    total = sum(values, MAX_ITEMS);
    printf("%s scored %d, grade %c, rate %.3f\n", name, total, grade, rate);
    return EXIT_SUCCESS;
}

/* the definition provides the body */
static int sum(const int *values, size_t n) {
    int acc = 0;
    for (size_t i = 0; i < n; i++) acc += values[i];
    return acc;
}
  • Types carry size and meaning: char is 1 byte, int is usually 4, and size_t is the unsigned type used for sizes and indices.
  • printf formats by hand: %d for int, %zu for size_t, %f for double, %c for char, %s for a string and %p for a pointer.
  • A wrong length modifier or conversion is undefined behaviour, not a friendly warning: the call reads the wrong number of bytes.
  • There is no bool before C99; include <stdbool.h> or use an int where 0 means false.
  • Arrays do not know their own length, so pass the count alongside the pointer.

Reading compiler and linker output

$ gcc -Wall -Wextra -c demo.c
demo.c: In function 'main':
demo.c:12:13: warning: format '%d' expects argument of type 'int', but argument 2
             has type 'const char *' [-Wformat=]
demo.c:20:5: error: 'count' undeclared (first use in this function)

# linker errors name symbols, not lines
$ gcc main.o util.o -o app
/usr/bin/ld: main.o: in function 'main':
main.c:(.text+0x2a): undefined reference to 'helper'
collect2: error: ld returned 1 exit status
💡
A compile error concerns one translation unit and points at a line. A link error means a symbol was declared but never compiled in or never found: undefined reference almost always means a missing object file or a missing -l library, not a missing declaration.

FAQ

gcc or clang?
Either. Both implement the same standard, and both support the sanitisers; clang's diagnostics are often easier to read. Standards compliance, not the compiler name, is what makes code portable.
Why does the compiler accept code that crashes at run time?
C trusts the programmer. Bounds, lifetimes and type correctness are largely your responsibility, which is also why it is fast and predictable. Compile with -Wall -Wextra and test under -fsanitize=address,undefined.

Pointers and memory Structs, files and undefined behaviour

Last refreshed 2026-09-18.