MINT lernen

Zusammenfassung

Alles Wichtige zu C und C++ auf einen Blick — die Befehle, Regeln und Fallen aus allen elf Unterkapiteln.

1

Einstieg in C

C wird vor dem Start komplett übersetzt. Jede Variable hat einen festen Typ, und das Programm startet immer in main.

2.1.1

Vom Quelltext zum Programm

C
#include <stdio.h>
int main(void) {
    printf("Hallo\n");
    return 0;
}
  • Präprozessor → Compiler → Linker
  • Fehlermeldungen von oben abarbeiten, -Wall für Warnungen
  • Python interpretiert, C übersetzt vorab
gcc hallo.c -o hallo · ./hallo

2.1.2

Datentypen und printf

  • int, double, float, char ('A')
  • deklarieren vor Gebrauch, Typ bleibt fest
  • 7 / 2 = 3, 7 % 2 = 1, 7.0 / 2 = 3.5
  • Cast: (double) a / b
  • %d %f %.2f %c %5d %%, \n, \t
printf("%8.2f", x) → 8 Zeichen breit

2.1.3

Kontrollstrukturen

  • if / else if / else, switch mit break
  • == != < <= && || !; 0 = falsch, sonst wahr
  • Falle: if (x = 5) ist immer wahr
  • while prüft vorher, do … while mind. einmal
for (int i = 0; i < n; i++) ≙ range(n)

2.1.4

Funktionen und Header

  • Rückgabetyp, Name, Parameter; void = kein Rückgabewert
  • Parameter sind Kopien (call by value)
  • Prototyp vor main oder in der .h
  • #include "rechner.h" + Include-Guard
gcc main.c rechner.c -o rechner
Übersetzen
Quelltext .c → Präprozessor → Compiler → Linker → ausführbare Datei
Nach jeder Änderung neu übersetzen, sonst läuft die alte Version.

Warum 7 / 2 nicht 3,5 ist

Der Typ des Ergebnisses richtet sich nach den Operanden, nicht nach der Zielvariable. Zwei int ergeben ein int — erst ein Cast oder 2.0 macht daraus eine Kommarechnung.

2

Nah an der Hardware

C gibt direkten Zugriff auf den Speicher: Adressen, Zeiger, Arrays — und läuft auf Mikrocontrollern.

2.2.1

Speicher und Adressen

  • Speicher = Folge von Bytes mit Adressen (hex)
  • typisch: char 1, int 4, double 8 Byte — sizeof misst nach
  • &x = Adresse, Ausgabe mit %p
  • Adressen ändern sich bei jedem Start
scanf("%d", &x);

2.2.2

Zeiger

C
int x = 4;
int *p = &x;   // p zeigt auf x
*p = 7;        // x ist jetzt 7
  • NULL = zeigt auf nichts
  • Zeigertyp passt zum Variablentyp
  • Zeigerparameter ändern Variablen des Aufrufers
void tausche(int *a, int *b) · tausche(&x, &y)

2.2.3

Arrays und Zeichenketten

  • int w[5] = {…}; → Indizes 0 … 4, keine Grenzprüfung
  • Anzahl: sizeof(w) / sizeof(w[0])
  • Array-Name = Adresse des ersten Elements
  • char s[] = "Lena"; belegt 5 Byte (mit \0)
  • strlen, strcpy, strcmp aus <string.h>
strcmp(a, b) == 0 statt a == b

2.2.4

Mikrocontroller

  • Arduino Uno: ATmega328P, 16 MHz, 2 KB RAM, 32 KB Flash
  • setup() einmal, loop() endlos
  • pinMode, digitalWrite, digitalRead, delay(ms)
  • INPUT_PULLUP: gedrückt = LOW
T = tan + taus · f = 1 / T
Zeiger in einem Satz
&x liefert die Adresse, *p den Wert dort
Deklaration: Typ * Name, z. B. int *p = &x; — der * gehört dann zur Deklaration, nicht zum Dereferenzieren.

Warum C keine Array-Grenzen prüft

C übersetzt einen Zugriff a[i] direkt in „Startadresse + i · Elementgröße“. Das ist schnell, aber niemand kontrolliert, ob i passt. Ein Zugriff daneben ist undefiniertes Verhalten — kein Compilerfehler.

3

Von C zu C++

C++ erweitert C um Streams, Zeichenketten, Referenzen und Klassen — fast jeder C-Code läuft weiter.

2.3.1

Was C++ ergänzt

C++
#include <iostream>
#include <string>
using namespace std;

string name;
cin >> name;
cout << "Hi " + name << endl;
  • string: + verketten, .length(), == vergleicht Inhalt
  • bool mit true/false
  • Referenz int &r = x;, Referenzparameter ohne & beim Aufruf
  • using namespace std; nicht in Header
g++ prog.cpp -o prog

2.3.2

Klassen in C++

C++
class Lampe {
private:
    bool an;
public:
    Lampe() { an = false; }
    void schalten() { an = !an; }
};              // Semikolon!
  • Objekt ohne new: Lampe l;, Aufruf l.schalten();
  • Kapselung: Attribute private, Methoden public
  • außerhalb: void Lampe::schalten(), Aufteilung .h / .cpp
  • struct = Klasse, standardmäßig public
class Name { private: … public: … };

2.3.3

Ein Konsolenspiel bauen

  • Zufallszahl, Schleife bis Treffer, Hinweise größer/kleiner, Versuche zählen
  • #include <cstdlib>, <ctime>
  • srand(time(0)) genau einmal
  • Halbieren: höchstens 7 Tipps für 1 … 100, da 27 = 128 ≥ 100
a + rand() % (b - a + 1) → a … b
Zufallszahl im Bereich
rand() % n → 0 … n − 1, also a + rand() % (b - a + 1) → a … b
Beispiel Würfel: 1 + rand() % 6 liefert 1 … 6.

Referenz oder Zeiger?

Beide erlauben einer Funktion, die Variable des Aufrufers zu ändern. Die Referenz ist bequemer (kein *, kein & beim Aufruf) und zeigt immer auf dieselbe Variable; ein Zeiger kann umgesetzt werden oder NULL sein.

4

Die Regeln, an denen die Punkte hängen

Diese Punkte kosten in Arbeiten zu C und C++ am häufigsten Punkte — prüfe sie bei jeder Aufgabe.

Ausgaben Zeile für Zeile verfolgen

Bei „Was gibt das Programm aus?“ eine Tracetabelle mit allen Variablen anlegen. Bei jeder Division prüfen: Sind beide Operanden int? Dann wird abgeschnitten.

Kopie, Adresse oder Referenz?

Vor jedem Funktionsaufruf klären: Wird ein Wert kopiert (int x), eine Adresse übergeben (int *x, Aufruf mit &) oder eine Referenz (int &x)? Nur die letzten beiden ändern die Variable des Aufrufers.

Grenzen und Endezeichen

Indizes laufen von 0 bis n − 1, Zeichenketten brauchen ein Byte für \0. Bei INPUT_PULLUP heißt gedrückt LOW, und srand steht nur einmal im Programm.

1AFB I — Reproduzieren10 Aufgaben› !Typische Fehler12 Fehler mit richtigem Code› ?Selbsttest40 Fragen mit Auswertung› ✎Probeklausur50 Punkte in 45 Minuten›