
Der Präprozessor ist ein echter Profi-Trick in C! Heute lernt ihr #define für Konstanten und Makros, wie ihr eigene Header-Dateien baut, und wie ihr mit #ifdef Code ein- und ausschalten könnt. Achtung bei den Klammern – da lauert eine fette Falle! 🪤
✏️ Übungen
#define lesen – Was kommt raus?
Gegeben sind folgende #define-Definitionen und Code-Schnipsel. Bestimme jeweils die Ausgabe. Achtung – bei einem Beispiel steckt die Klammer-Falle!
#define BREITE 8 #define HOEHE 5 #define FLAECHE (BREITE * HOEHE) #define QUADRAT_GUT(x) ((x)*(x)) #define QUADRAT_SCHLECHT(x) x*x /* Snippet A */ printf("%d\n", BREITE); /* Snippet B */ printf("%d\n", FLAECHE); /* Snippet C */ printf("%d\n", QUADRAT_GUT(3+2)); /* Snippet D – Achtung: Klammer-Falle! */ printf("%d\n", QUADRAT_SCHLECHT(3+2));
| Snippet | Textersetzung durch Präprozessor | Ausgabe |
|---|---|---|
| A | ||
| B | ||
| C | ||
| D |
Erkläre in einem Satz warum Snippet C und D unterschiedliche Ergebnisse liefern:
Konstanten definieren – Mehrwertsteuer-Rechner
Definiere mit #define die folgenden Konstanten und schreibe dann ein Programm, das den Bruttobetrag berechnet und ausgibt.
MWST= 0.20 (20% Mehrwertsteuer)PREIS_NETTO= 100.0 (Nettopreis in Euro)
Das Programm soll ausgeben: Nettopreis: 100.00 EUR und Bruttopreis: 120.00 EUR
Bonusfrage: Könnte man brutto auch als #define schreiben statt als Variable? Wenn ja – wie?
Makro schreiben – ABSOLUT(x)
Schreibe ein Makro ABSOLUT(x), das den Absolutwert einer Zahl zurückgibt. Verwende den ternären Operator ? :. Denke an die Klammern!
Teste dein Makro mit folgenden Werten und schreibe die erwartete Ausgabe auf:
Erwartete Ausgaben (fülle aus):
| Aufruf | Erwartete Ausgabe |
|---|---|
| ABSOLUT(-7) | |
| ABSOLUT(5) | |
| ABSOLUT(0) | |
| ABSOLUT(-3+1) |
((x) >= 0 ? (x) : -(x)) – alle Parameter in Klammern!Bedingte Kompilierung – Debug-Modus
Schreibe ein Programm das eine einfache Berechnung durchführt. Wenn DEBUG definiert ist, sollen zusätzliche Debug-Ausgaben erscheinen. Wenn nicht – nur das Ergebnis.
Implementiere zwei Varianten:
- Oben im Code
#define DEBUGgesetzt → Debug-Info erscheint - Dieses
#defineauskommentiert → nur das Ergebnis
Ausgabe MIT DEBUG (schreibe auf was ausgegeben wird):
Ausgabe OHNE DEBUG:
Wie kann man DEBUG beim Kompilieren von außen aktivieren, ohne den Quellcode zu ändern?
#ifdef prüft ob ein Name definiert wurde – egal welchen Wert er hat. gcc -DDEBUG datei.c definiert DEBUG von der Kommandozeile!Include Guard – Header-Datei schreiben
Schreibe eine Header-Datei rechner.h mit Funktionsdeklarationen für einen einfachen Taschenrechner. Vergiss den Include Guard nicht! Schreibe dann die zugehörige main.c die den Header einbindet.
Datei: rechner.h
Datei: main.c
Erkläre in einem Satz was passiert, wenn man den Include Guard weglässt und rechner.h aus zwei verschiedenen .c-Dateien eingebunden wird:
#ifndef DATEINAME_H → #define DATEINAME_H → Inhalt → #endif. Der Name muss pro Header-Datei eindeutig sein!CLAMP-Makro schreiben
Schreibe ein Makro CLAMP(x, min, max) das einen Wert auf den Bereich [min, max] begrenzt:
- Wenn x < min → gibt min zurück
- Wenn x > max → gibt max zurück
- Sonst → gibt x zurück
Tipp: Du kannst dein MAX- und MIN-Makro kombinieren, oder den ternären Operator zweimal verschachteln.
Erwartete Ausgaben (fülle aus):
| Aufruf | Ergebnis | Warum? |
|---|---|---|
| CLAMP(-5, 0, 10) | ||
| CLAMP(5, 0, 10) | ||
| CLAMP(15, 0, 10) | ||
| CLAMP(1.5, 0.0, 1.0) |
Wo wird CLAMP in der Praxis eingesetzt? Nenne ein Beispiel aus der echten Programmierung:
MAX((lo), MIN((x), (hi))) – probiere es aus und erkläre warum das funktioniert!✅ Selbst-Checkliste Unit 32
- Ich kann #define-Konstanten korrekt definieren (Großbuchstaben, kein Semikolon)
- Ich verstehe warum Makro-Parameter in Klammern müssen (QUADRAT-Falle)
- Ich kann MAX, MIN, ABSOLUT als Makros schreiben
- Ich kenne den Unterschied zwischen <system.h> und "eigen.h"
- Ich kann einen korrekten Include Guard (#ifndef/#define/#endif) schreiben
- Ich nutze #ifdef DEBUG für bedingte Debug-Ausgaben
- Ich weiß wie man mit gcc -DNAME ein Symbol von außen definiert