C Mastery / Program Structure, Translation Units, and the First Program
Part 1 — The Core Language

Program Structure, Translation Units, and the First Program

This chapter introduces the skeleton of every C program and the concept of a translation unit. The translation unit is the fundamental unit of compilation, and everything later depends on understanding it.

Why This Matters

You cannot reason about scope, linkage, headers, or multi-file programs without knowing what a translation unit is. The first program also anchors the exact shape of C: a main function, a return value, and the boundary between your code and the runtime.

Prerequisites

Core Concept

The minimal program

Every hosted C program has a main function. The simplest conforming program is:

int main(void)
{
    return 0;
}

int is the return type, main is the function name, (void) says the function takes no arguments, and return 0 returns a status to the environment. Returning 0 conventionally means success.

What a translation unit is

A translation unit is what the compiler actually translates. It is a source file *after* preprocessing. In simple terms, it is your .c file with every #include replaced by the included file's contents and every macro expanded.

Each .c file (plus everything it includes) becomes one translation unit, and is compiled independently of every other translation unit. The linker later combines the results.

Syntax

main forms

The C standard specifies two portable forms of main:

int main(void)                    /* no command-line access */
int main(int argc, char *argv[])  /* command-line access */

Some implementations accept void main(void) or other forms, but those are non-portable. int is the portable return type. The parameters are covered in c.core.17 (functions) and c.stdlib.3 (command-line processing).

Comments

C89 supports block comments only:

/* This is a block comment. */

C99 and later support line comments:

// This is a line comment, available since C99.

Block comments do not nest. A /* inside a /* ... */ comment is just a character; the comment ends at the first */.

Examples

Minimal program with command-line access

int main(int argc, char *argv[])
{
    (void)argc;   /* unused for now */
    (void)argv;   /* unused for now */
    return 0;
}

The (void)argc casts suppress "unused parameter" warnings. This is the portable idiom; some compilers also support __attribute__((unused)) (GCC) or [[maybe_unused]] (C23), but the cast works everywhere.

Program that returns a nonzero status

int main(void)
{
    return 1;  /* conventionally indicates an error */
}

Returning EXIT_SUCCESS or EXIT_FAILURE from <stdlib.h> is more portable than hard-coding 0 and 1, but 0 and EXIT_SUCCESS are both defined to report success.

A complete translation unit after preprocessing (conceptual)

Given prog.c:

#include <stdio.h>

int main(void)
{
    return 0;
}

The translation unit is prog.c with the contents of <stdio.h> (typically thousands of lines of declarations) inserted in place of the #include directive. The compiler sees the *combination* as one unit.

How It Works

When you compile prog.c:

1. Preprocessing produces the translation unit: directives are executed, macros expanded, includes inserted, and comments removed. 2. Compilation proper turns the translation unit into assembly or an intermediate representation. 3. Assembly turns that into an object file (machine code plus symbols and relocation records). 4. Linking combines object files and libraries into an executable.

A single translation unit can reference a name defined in another translation unit (an *external* symbol). The linker resolves those references. This is why declarations and definitions are separate concepts (c.core.6) and why linkage matters (c.core.35).

Variations

Free-standing main

In a freestanding environment there is no required main. The entry point is implementation-defined and is usually the reset handler. Part 13 covers this.

Implementation-defined startup

The C standard says the function called at program startup is named main. Everything *before* main — the runtime startup that initializes the C runtime, sets up argv, and calls main — is implementation-specific. It exists, but it is not part of ISO C.

Common Mistakes

Use int main.

} of main implicitly returns 0. In C89 the return value was unspecified. Always write the return explicitly.

whose *definitions* live in a separately compiled library.

Undefined Behavior

non-void value without a return is undefined behavior. (The exception is main, where falling off the end is defined in C99 and later to return 0.) VERIFIED

environment) is not portable and may be undefined or implementation-defined depending on the implementation. STANDARD-VERSION-DEPENDENT

Portability

VERIFIED

(array parameters decay; see c.arr.decay).

Under the Hood

The object file produced from a translation unit contains:

patch it at link time."

The linker merges these and produces an executable. Part 5 develops all of this.

Practical Usage

Every real C program is a set of translation units. The most common structure is:

src/
  main.c       // defines main
  util.c       // some functions
  util.h       // declarations for util.c

main.c includes util.h to get declarations, and the linker joins the two object files. This is covered fully in c.core.39.

Exercises

1. Write, compile, and run a minimal int main(void) program that returns 0. Verify with your shell that the exit status is 0. 2. Write a program that returns a nonzero value and verify the exit status. 3. Determine what compiler you are using and which C standard it defaults to. For GCC/Clang: gcc -dM -E - < /dev/null | grep __STDC_VERSION__ (this prints the standard version macro). 4. Run the preprocessor on a simple file and observe the translation unit. For GCC/Clang: gcc -E prog.c.

Deep Challenge

Using only the C standard (or the official documentation for your compiler), answer: in a hosted environment, what are the exact constraints the standard places on the declaration of main? What happens if main is declared static? Write a short note with citations to the relevant section of the standard.

References

Verification

VERIFIED

STANDARD-VERSION-DEPENDENT

verified.`

Progress

Concept checkboxes

Mastery levels

ConceptCurrent level (0–8)Target level
c.lang.program03
c.lang.tu03