The VikiD Truth

Knowledge base / Computing / C & systems languages

computingFreedom | Build | Picolisp | Picolisp Machine | Pil Sources | Linux | BASH | C-Programmming | Operating Systems | Javascipt | Emacs | vim | Pharo Smalltalk | Computer Security | Python | The Compiler | Identifiers | Literals | storage_linkage |

C Syntax

Here is the truth about C’s syntax: there is very little of it. A handful of control structures, a few ways to declare things, and that is the whole grammar most programs use. This page is the cheat sheet, but first a few words on why it is shaped the way it is, so it sticks.

What it is, in plain words

C programs are built from three kinds of pieces:

Any expression followed by ; is a statement. A block groups statements and starts a new scope for the names declared inside it (see Identifiers).

Why it matters

Almost every language that came after borrowed this syntax: C++, Java, C#, JavaScript, Go, Rust, Zig, Odin, PHP. Learn C’s control flow and you can read half the code in the world. The quirks matter too: fall-through in switch, the dangling else, = versus ==. Those quirks were copied as well.

An everyday analogy: a recipe card

Declarations are the ingredient list. Expressions are the actual actions (“whisk two eggs”). Statements are the instructions about order: “if the batter is lumpy, whisk again”, “repeat for each layer”, “stop when golden”. A recipe with no ingredient list makes no sense, and C agrees: since C99 you must declare a function before you call it.

A hands-on example: all the structures in one program

#include <stdio.h>
#include <stdbool.h>   /* not needed in C23, where bool is a keyword */

enum colour { RED, GREEN, BLUE };

typedef struct {
    const char *name;
    enum colour c;
} item;

static const char *colour_name(enum colour c) {
    switch (c) {
    case RED:   return "red";
    case GREEN: return "green";
    case BLUE:  return "blue";
    default:    return "?";
    }
}

int main(void) {
    item items[] = { {"apple", RED}, {"leaf", GREEN}, {"sky", BLUE}, {"lime", GREEN} };
    int n = sizeof items / sizeof items[0];
    int greens = 0;

    for (int i = 0; i < n; i++) {
        if (items[i].c != GREEN)
            continue;               /* skip non-green */
        greens++;
        printf("%s is %s\n", items[i].name, colour_name(items[i].c));
    }

    int k = 0;
    do {
        k++;
    } while (k < greens);

    printf("%d greens, loop ran %d times\n", greens, k);
    return 0;
}
gcc -std=c23 -Wall -Wextra syntax.c -o syntax && ./syntax

Notice return inside switch means no break is needed. Notice for (int i = 0; ...): declaring the loop variable inside the for has been legal since C99 and is normal style today.

Common misconceptions

Connections

The cheat sheet

Last edited · 17 revisions

Tags: #Computing