Add Checkpoint solution: checkpoint_a.c

This commit is contained in:
2026-04-15 00:26:04 +02:00
parent 32ae4b8fae
commit d1fc3fdb2c

181
exercises/checkpoint_a.c Normal file
View File

@@ -0,0 +1,181 @@
// ============================================
// Checkpoint A: Memory & Datentypen
// Lösung für Selbsttest nach Modul 1-2
// ============================================
#include <stdio.h>
#include <stdint.h>
#include <limits.h>
#include <stdbool.h>
// ============================================
// AUFGABE 1: Stack vs Heap Analyse
// ============================================
void aufgabe1_memory_analyse() {
printf("=== AUFGABE 1: Memory-Analyse ===\n\n");
// Gegeben: Was passiert hier?
printf("Code:\n");
printf("void test() {\n");
printf(" int x = 42; // Stack\n");
printf(" int *p = &x; // Stack (Pointer)\n");
printf(" int *heap = malloc(4); // Heap\n");
printf(" *heap = 100;\n");
printf("} // <- Was wird freigegeben?\n\n");
// Lösung:
printf("LÖSUNG:\n");
printf("1. x (int, Wert 42) -> Stack -> AUTOMATISCH freigegeben\n");
printf("2. p (Pointer auf x) -> Stack -> AUTOMATISCH freigegeben\n");
printf("3. heap (Pointer-Wert) -> Stack -> AUTOMATISCH freigegeben\n");
printf("4. *heap (int, Wert 100) -> Heap -> NICHT freigegeben! MEMORY LEAK!\n\n");
printf("Fehler: Kein free(heap) vorhanden!\n\n");
}
// ============================================
// AUFGABE 2: Typ-Grenzen und Overflow
// ============================================
void aufgabe2_typ_grenzen() {
printf("=== AUFGABE 2: Typ-Grenzen ===\n\n");
printf("Frage: Was ist der Output?\n");
printf("short s = 32767;\n");
printf("s = s + 1;\n");
printf("printf(\"%%d\\n\", s);\n\n");
// Demonstrieren
short s = 32767;
printf("Vor: s = %d\n", s);
s = s + 1;
printf("Nach: s = %d\n\n", s);
printf("LÖSUNG: -32768 (Overflow bei signed short!)\n");
printf("32767 ist SHRT_MAX, +1 ergibt -32768 (SHRT_MIN)\n");
printf("Bei signed integer overflow ist Verhalten undefiniert!\n\n");
}
// ============================================
// AUFGABE 3: Pointer-Dereferenzierung
// ============================================
void aufgabe3_pointer() {
printf("=== AUFGABE 3: Pointer ===\n\n");
printf("Frage: Was ist der Output?\n");
printf("int a = 5, b = 10;\n");
printf("int *p1 = &a, *p2 = &b;\n");
printf("p1 = p2;\n");
printf("*p1 = 20;\n");
printf("printf(\"%%d %%d\\n\", a, b);\n\n");
// Demonstrieren
int a = 5, b = 10;
int *p1 = &a, *p2 = &b;
p1 = p2; // p1 zeigt jetzt auch auf b!
*p1 = 20; // b wird 20!
printf("Output: %d %d\n\n", a, b);
printf("LÖSUNG: 5 20\n");
printf("- a bleibt 5 (unverändert)\n");
printf("- p1 zeigt nach p1=p2 auf b\n");
printf("- *p1 = 20 ändert b auf 20\n");
printf("- a wurde nie verändert!\n\n");
}
// ============================================
// AUFGABE 4: Memory-Layout Visualisierung
// ============================================
void aufgabe4_memory_layout() {
printf("=== AUFGABE 4: Memory-Layout ===\n\n");
printf("Aufgabe: Zeichne das Memory-Layout für:\n");
printf("void foo() {\n");
printf(" int x = 10; // Line 1\n");
printf(" int *p = malloc(4); // Line 2\n");
printf(" *p = 20; // Line 3\n");
printf(" int arr[3] = {1,2,3}; // Line 4\n");
printf("}\n\n");
printf("LÖSUNG (nach Line 4):\n");
printf("┌─────────────────┐\n");
printf("│ Stack │\n");
printf("│ ┌───────────┐ │\n");
printf("│ │ x = 10 │ │ <- int (4 Bytes)\n");
printf("│ ├───────────┤ │\n");
printf("│ │ p = 0x... │ │ <- Pointer (8 Bytes auf 64-bit)\n");
printf("│ │ (zeigt │ │\n");
printf("│ │ auf Heap)│ │\n");
printf("│ ├───────────┤ │\n");
printf("│ │ arr[0]=1 │ │ <- Array (12 Bytes = 3*4)\n");
printf("│ │ arr[1]=2 │ │\n");
printf("│ │ arr[2]=3 │ │\n");
printf("│ └───────────┘ │\n");
printf("└─────────────────┘\n");
printf("\n");
printf("\n");
printf("┌─────────────────┐\n");
printf("│ Heap │\n");
printf("│ ┌───────────┐ │\n");
printf("│ │ *p = 20 │ │ <- malloc(4)\n");
printf("│ └───────────┘ │\n");
printf("└─────────────────┘\n\n");
printf("Nach foo() Ende:\n");
printf("- Stack: Alles freigegeben (x, p, arr)\n");
printf("- Heap: *p BLEIBT (Memory Leak ohne free!)\n\n");
}
// ============================================
// BONUS: Typ-Sicherheit mit Fixed-Width
// ============================================
void bonus_fixed_width() {
printf("=== BONUS: Fixed-Width Typen ===\n\n");
printf("Vorteile von stdint.h:\n\n");
printf("Statt 'int' (Größe variiert):\n");
printf(" int32_t x; // Garantiert 32-bit\n");
printf(" int64_t y; // Garantiert 64-bit\n");
printf(" uint8_t z; // Garantiert 8-bit, unsigned\n\n");
printf("Präfixe:\n");
printf(" int = signed\n");
printf(" uint = unsigned\n");
printf(" 8/16/32/64 = Bits\n\n");
printf("Beispiel Portabilität:\n");
int32_t portabel = 100; // Überall 32-bit
printf(" int32_t: %zu Bytes (immer 4)\n", sizeof(portabel));
printf(" int: %zu Bytes (kann 2, 4 oder 8 sein)\n\n", sizeof(int));
}
// ============================================
// HAUPTPROGRAMM
// ============================================
int main() {
printf("╔══════════════════════════════════════════════════════════╗\n");
printf("║ CHECKPOINT A: LÖSUNGEN (Memory & Datentypen) ║\n");
printf("╚══════════════════════════════════════════════════════════╝\n\n");
printf("Diese Datei enthält die Lösungen für Checkpoint A.\n");
printf("Vergleiche mit deinen Antworten!\n\n");
aufgabe1_memory_analyse();
aufgabe2_typ_grenzen();
aufgabe3_pointer();
aufgabe4_memory_layout();
bonus_fixed_width();
printf("╔══════════════════════════════════════════════════════════╗\n");
printf("║ ZUSAMMENFASSUNG ║\n");
printf("╠══════════════════════════════════════════════════════════╣\n");
printf("║ ✓ Stack: Automatisch, schnell, begrenzt ║\n");
printf("║ ✓ Heap: Manuell, flexibel, persistent ║\n");
printf("║ ✓ malloc/free immer paaren! ║\n");
printf("║ ✓ Pointer = Adresse, * = Wert an Adresse ║\n");
printf("║ ✓ Integer-Overflow = undefiniertes Verhalten ║\n");
printf("║ ✓ Fixed-Width Typen (stdint.h) für Portabilität ║\n");
printf("╚══════════════════════════════════════════════════════════╝\n");
return 0;
}