Überblick
Dieser Leitfaden führt Schritt für Schritt durch das Erstellen und Kompilieren von C-Programmen unter Linux mithilfe des Standardwerkzeugs cc. Angefangen bei der Bereitstellung der nötigen Entwicklungswerkzeuge über elementare Single-File-Builds bis hin zu unverzichtbaren Compiler-Flags wie -o oder -Wall sowie modularen Multi-File-Kompilierungsmethoden richtet sich dieser Artikel gezielt an Einsteiger, die eine solide Arbeitsgrundlage suchen.
Entwicklungsumgebung für C einrichten und cc prüfen
Bevor C-Quelltexte unter Ubuntu übersetzt werden können, muss die Basis-Toolchain installiert sein. Das Metapaket build-essential liefert alle dafür erforderlichen Compiler und Bibliotheken:
sudo apt-get update -qq && sudo apt-get install -y build-essential

Um zu prüfen, welcher C-Compiler im Pfad hinterlegt ist und welches Binary hinter dem Standardaufruf steht, dient das Kommando which cc:

Der Aufruf cc dient als Standardschnittstelle des Systems, um Quellcode in ausführbaren Maschinencode zu transformieren. Über das Flag cc --version lässt sich die exakte Versionsnummer sowie die zugrundeliegende Toolchain (in der Regel GCC) abfragen.
⚙️ [Zentrale Compiler-Optionen im Überblick]
-o : Legt den Zieldateinamen der generierten ausführbaren Binärdatei fest.-c : Erzeugt Objektdateien (.o) und unterbindet vorerst die Linker-Phase.-Wall : Aktiviert sämtliche praxisrelevanten Warnhinweise des Compilers.-g : Bettet Debugging-Symbole zur späteren Fehleranalyse via GDB ein.-O2 : Wendet umfassende Code-Optimierungen für eine gesteigerte Laufzeiteffizienz an.

Erstes C-Programm erstellen und direkt übersetzen
Für eine saubere Strukturierung empfiehlt sich ein eigener Arbeitsordner. Mit folgendem Befehl wird das Verzeichnis ~/c_practice erstellt und direkt dorthin gewechselt:
mkdir -p ~/c_practice && cd ~/c_practice

Anschließend wird ein einfaches Minimalprogramm mit der Bezeichnung hello.c mittels cat angelegt:

Um die Datei ohne zusätzliche Parameter direkt zu übersetzen, genügt der Aufruf cc hello.c. Fehlt die Angabe eines Ausgabepfads, vergibt das System standardmäßig den Namen a.out für das resultierende Binary:

Das erzeugte Programm lässt sich nun durch den Aufruf ./a.out direkt im Terminal ausführen. Die Konsole gibt daraufhin erwartungsgemäß den formatierten Begrüßungstext aus:

Ausgabedatei festlegen (-o) und Compiler-Flags (-Wall, -O2)
Im nächsten Schritt demonstrieren wir den Einsatz von Compiler-Parametern anhand eines kleinen Rechenbeispiels (calc.c):

In professionellen Entwicklungsworkflows sollte niemals unkontrolliert ohne Warnungen gebaut werden. Die Option -Wall fängt potenziellen fehlerhaften Code frühzeitig ab, während -O2 für eine performante Codeerzeugung sorgt. Über -o calc_app wird das finale Kompilat gezielt benannt:
cc -Wall -O2 -o calc_app calc.c

Mit ls -l calc_app lässt sich verifizieren, ob das Binary ordnungsgemäß angelegt wurde und die erforderlichen Ausführungsrechte (x) besitzt:

Ein anschließender Probelauf über ./calc_app bestätigt die korrekte Ausführung der programmierten Additionslogik:

Modulare Übersetzung (-c) und Linken mehrerer Objektdateien
Größere Softwareprojekte werden selten monolithisch in einer einzelnen Quellcodedatei verwaltet. Zur Demonstration einer modularen Struktur erzeugen wir zunächst die Header-Datei message.h mit der Funktionssignatur:

Die tatsächliche Implementierung der deklarierten Routine wandert in die Quellcodedatei message.c:

Den Einstiegspunkt der Anwendung bildet schließlich main.c, worin die externe Funktion aufgerufen wird:

Mithilfe des Schalters -c wird der Link-Vorgang zunächst ausgelassen. Der Compiler erzeugt für jede .c-Datei isoliert eine eigenständige Maschinencode-Zwischenstufe in Form einer Objektdatei (.o):
cc -c message.c main.c

Ein Kontrollblick mit ls -l *.o zeigt die erzeugten Zwischenstände message.o und main.o im Verzeichnis:

Nun führt ein zweiter Schritt die einzelnen Objektdateien zusammen: Der Linker verknüpft alle Funktionsaufrufe und baut die finale ausführbare Datei modular_app:
cc -o modular_app message.o main.o

Das daraus resultierende modulare Programm lässt sich via ./modular_app starten und führt den Funktionscode modulübergreifend erfolgreich aus:

Dieser Praxisleitfaden hat das grundlegende Handwerkszeug rund um den Aufruf von cc unter Ubuntu vermittelt – vom einfachen Einzeiler-Build bis hin zur strukturierten modularen Übersetzung. Diese Compiler-Grundlagen bilden das verlässliche Fundament für anspruchsvollere Softwareprojekte im Linux-Ökosystem.