Lexical Structure

Every C program is a sequence of tokens — keywords, identifiers, literals, operators, and punctuation — grouped into statements inside blocks. This page defines the vocabulary before we build sentences.

Statements & Blocks

A statement is one instruction ending with a semicolon ; — the period of the C language. A block is zero or more statements wrapped in curly braces { }. Blocks group statements so that if, loops, and functions can execute several instructions as one unit, and they create a new scope for local names.

int main(void) {          // { opens the function block
    int a = 1;            // declaration statement
    int b = 2;            // another declaration
    a = a + b;            // assignment statement (expression + ;)
    return a;             // return statement
}                         // } closes the block

C is a free-form language: spaces, tabs, and newlines are insignificant outside string literals and comments. Use indentation only for the reader — the compiler does not care. Semicolons are mandatory; forgetting one is the most common beginner compile error.

Declarations Introduce Names

Every name must be declared with a type before use — that is how the compiler knows how many bytes it occupies and what the operators may do with it. A declaration can also initialize the variable in the same statement:

int score = 100;            // declares int 'score', initial value 100
double pi = 3.14159;        // declares double 'pi' with an approximate value
char letter = 'A';          // one character, quoted with single quotes
int count;                  // declared but NOT initialized — contains garbage

Comments

Two comment forms exist. Use // for a line note (standard since C99) and /* ... */ for multi-line or block notes, which can also disable code temporarily.

// single-line comment: everything to the end of the line is ignored

/* block comment:
   can span several lines and is
   often used for file headers */

int x = 1; /* comments may sit inside a line */ int y = 2;

Comments cannot be nested in standard C — a /* inside a /* ... */ block ends the block at the first */. Keep comments about why, never about what; the code already says what.

Identifiers & Keywords

An identifier names a variable, function, type, or label. It must start with a letter or underscore and continue with letters, digits, or underscores; it is case-sensitive (Score and score differ). Avoid leading underscores — names starting with _ are reserved for the implementation.

A keyword is a reserved word you cannot use as an identifier. The C11 reserved set, grouped by purpose:

GroupKeywords
Control flowif else while do for switch case default break continue goto
Typesint char float double void short long signed unsigned struct union enum _Bool _Complex
Storage & qualifiersstatic extern auto register const volatile restrict inline _Thread_local
Miscreturn sizeof typedef _Alignas _Alignof _Static_assert _Atomic _Generic _Noreturn

Operators & Expressions

Operators combine operands into expressions. Everything below evaluates to a value of some type; the type rules matter more in C than anywhere else, and the types page explains those rules. The main families:

FamilyOperatorsExample
Arithmetic+ - * / %total / count
Assignment= += -= *= /= %=sum += item;
Comparison== != < > <= >=score >= 60
Logical&& || !a > 0 && b > 0
Bitwise& | ^ ~ << >>flags & 0xFF
Address& * sizeof&x, *p
Other?: ++ -- , -> .i++, p->field

Precedence decides grouping when operators compete: the classic pitfall is flags & mask == mask parsing as flags & (mask == mask). When in doubt, add parentheses — clarity beats cleverness, and compilers optimize both identically.

A Small Complete Program

Here is the lexical toolkit assembled into one program: declaration, arithmetic, a comment, a loop, and a condition — all forms you will use in every exercise that follows.

#include <stdio.h>   // printf() declaration

int main(void) {
    // sum the first five integers with a for loop
    int sum = 0;                    // accumulator, initialized to zero
    for (int i = 1; i <= 5; i++) {  // declare, test, increment
        sum += i;                   // compound assignment: sum = sum + i
    }
    // decision: report the parity of the result
    if (sum % 2 == 0) {
        printf("sum %d is even\n", sum);
    } else {
        printf("sum %d is odd\n", sum);
    }
    return 0;   // success exit status
}

Next: the data types that give those operators their meaning.