Wiederholung: Void-Pointer
Teil des Abschnitts Objektorientierte Programmierung der C-Journey von Coddy. Lektion 49 von 61.
Ein void* ist die Art von C zu sagen: „ein Zeiger auf etwas, aber ich sage dir nicht, worauf.“ Er kann die Adresse jedes Datentyps enthalten: eines int, eines float, einer Struktur oder irgendetwas anderem. Das macht ihn zur Grundlage für das Schreiben generischen Codes in C.
Der Haken ist, dass du einen void* nicht direkt dereferenzieren kannst. Der Compiler weiß nicht, wie viele Bytes gelesen oder wie sie interpretiert werden sollen. Um die Daten zu verwenden, musst du sie wieder in den korrekten Typ umwandeln:
void print_int(void* data) {
int* p = (int*)data;
printf("%d\n", *p);
}
int main() {
int x = 42;
print_int(&x);
return 0;
}Diese Flexibilität bringt Verantwortung mit sich. Wenn du in den falschen Typ umwandelst, wird der Compiler dich nicht daran hindern, aber dein Programm wird unbrauchbare Daten erzeugen oder abstürzen. Deshalb kombinieren generische Funktionen häufig einen void* mit einem Typindikator (wie einem Enum oder Flag), damit die Funktion weiß, wie sie die Daten korrekt interpretieren soll.
In den kommenden Lektionen wirst du void* verwenden, um Container zu erstellen, die Daten jeden Typs speichern können, und dadurch wirklich wiederverwendbare Datenstrukturen zu ermöglichen.
Aufgabe
EinfachSchreibe eine Funktion namens print_value, die zwei Parameter akzeptiert: einen void*-Zeiger auf Daten und ein int-Typ-Flag. Die Funktion soll die Daten anhand des Typ-Flags interpretieren und ausgeben:
- Wenn das Typ-Flag
0ist, wandle den Zeiger inint*um und gib den Ganzzahlwert aus - Wenn das Typ-Flag
1ist, wandle den Zeiger infloat*um und gib den Gleitkommawert mit 2 Dezimalstellen aus
Dein Programm erhält zwei Eingaben:
- Ein Typ-Flag (
0für Ganzzahl,1für Gleitkommazahl) - Einen numerischen Wert
Speichere den Wert abhängig vom Typ-Flag im passenden Variablentyp und rufe anschließend print_value mit einem Zeiger auf diese Variable und dem Typ-Flag auf.
Beispielausgabe bei den Eingaben 0 und 42:
42Beispielausgabe bei den Eingaben 1 und 3.14:
3.14Beispielausgabe bei den Eingaben 0 und -17:
-17Beispielausgabe bei den Eingaben 1 und 99.5:
99.50Probier es selbst
#include <stdio.h>
// TODO: Schreibe hier deine print_value-Funktion
int main() {
int type_flag;
scanf("%d", &type_flag);
if (type_flag == 0) {
int int_value;
scanf("%d", &int_value);
// TODO: Rufe print_value mit einem Zeiger auf int_value und dem type flag auf
} else if (type_flag == 1) {
float float_value;
scanf("%f", &float_value);
// TODO: Rufe print_value mit einem Zeiger auf float_value und dem type flag auf
}
return 0;
}Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der modularen Programmierung
Header-DateienInclude GuardsQuelldateienStatische FunktionenWiederholung: Modularer Taschenrechner4Kapselung
Konzept der Opaque PointersOpaque Structs definierenGetter und SetterValidierung in SetternRückblick: Die geheime Box7Funktionszeiger
Funktionszeiger deklarierenFunktionszeiger aufrufenTypedef für FunktionszeigerFunktionen als Argumente übergebenZusammenfassung: Calculator Dispatch10Generische Container
Wiederholung: Void-PointerGenerischer WrapperGenerisches SwapGenerisches VergleichenWiederholung: Generisches Array2Objekte und Methoden
Structs als ObjekteDer 'Self'-PointerConst-CorrectnessPointer vs. WertHilfsmethodenZusammenfassung: Point Manager5Projekt: Einfaches Bankkonto
Projekt-SetupImplementierung des Kontos3Objekt-Lebenszyklus
Konstruktor-MusterDestruktor-MusterStack-InitialisierungTiefe KopieRückblick: String-Wrapper6Vererbung durch Komposition
Struct-EinbettungDie First-Member-RegelZugriff auf Parent-MemberUpcastingRückblick: Formenhierarchie9Projekt: Formen-Zeichner
ProjektübersichtKreis-ImplementierungRechteck-ImplementierungPolymorphe VerwendungShape-ContainerÜbe selbstständig: Online-C-Compiler