Menu
Coddy logo textTech

Const-Correctness

Teil des Abschnitts Object Oriented Programming der C-Journey von Coddy — Lektion 8 von 61.

Beim Schreiben von Funktionen, die als Methoden fungieren, sollten einige das Objekt verändern (wie player_take_damage), während andere nur Daten lesen sollten, ohne etwas zu ändern. Das Schlüsselwort const ermöglicht es Ihnen, diese Unterscheidung auf Compilerebene zu erzwingen.

Indem Sie einen Pointer-Parameter als const markieren, versprechen Sie, dass die Funktion die Daten, auf die er zeigt, nicht verändern wird. Wenn Sie versehentlich versuchen, ein Mitglied zu ändern, wird der Compiler einen Fehler erzeugen:

typedef struct {
    int x;
    int y;
} Point;

// Diese Funktion kann den Punkt nur LESEN
void point_print(const Point *self) {
    printf("(%d, %d)\n", self->x, self->y);
    // self->x = 10;  // FEHLER: kann nicht über einen const-Pointer geändert werden
}

// Diese Funktion kann den Punkt MODIFIZIEREN
void point_move(Point *self, int dx, int dy) {
    self->x += dx;
    self->y += dy;
}

Der Parameter const Point *self teilt sowohl dem Compiler als auch anderen Programmierern mit, dass point_print eine „Getter“- oder schreibgeschützte Operation ist. Dies wird als Const-Korrektheit bezeichnet – die Verwendung von const überall dort, wo keine Änderung erforderlich ist.

Diese Praxis fängt Fehler frühzeitig ab. Wenn Sie eine Anzeige-Funktion schreiben und versehentlich ein Feld ändern, stoppt Sie der Compiler sofort, anstatt den Fehler in Ihr Programm schlüpfen zu lassen.

challenge icon

Aufgabe

Einfach

Lassen Sie uns ein Temperature-Modul erstellen, das einen Temperaturwert speichert und sowohl schreibgeschützte als auch modifizierende Operationen bereitstellt. Dies wird Ihnen helfen, die Verwendung von const-Pointern zu üben, um klar zwischen Funktionen zu unterscheiden, die Daten nur lesen, und solchen, die sie ändern.

Sie werden drei Dateien erstellen:

  • temperature.h: Deklarieren Sie ein Temperature-Struct mit einem einzelnen double celsius-Member. Deklarieren Sie außerdem drei Funktionen:
    • temp_display — nimmt einen const-Pointer auf Temperature entgegen und gibt die aktuelle Temperatur aus (schreibgeschützt)
    • temp_adjust — nimmt einen regulären Pointer auf Temperature und einen double-Betrag entgegen und addiert den Betrag zu celsius (modifizierend)
    • temp_to_fahrenheit — nimmt einen const-Pointer auf Temperature entgegen und gibt den in Fahrenheit umgerechneten Wert zurück (schreibgeschützt)
    Verwenden Sie Include-Guards mit dem Symbol TEMPERATURE_H.
  • temperature.c: Implementieren Sie alle drei Funktionen. Die Funktion temp_display sollte im Format "Current: %.1fC\n" drucken. Die Funktion temp_to_fahrenheit sollte celsius * 9.0 / 5.0 + 32.0 zurückgeben. Denken Sie daran, dass Funktionen, die const-Pointer verwenden, die Daten des Structs nicht ändern können.
  • main.c: Erstellen Sie eine Temperature-Instanz, führen Sie Operationen aus und zeigen Sie die Ergebnisse an.

Sie erhalten zwei Eingaben: den initialen Celsius-Wert (als double) und den Anpassungsbetrag (als double).

In Ihrer Hauptdatei:

  1. Initialisieren Sie eine Temperature mit dem initialen Celsius-Wert
  2. Rufen Sie temp_display auf, um die Starttemperatur anzuzeigen
  3. Rufen Sie temp_adjust auf, um die Temperatur um den Anpassungsbetrag zu ändern
  4. Rufen Sie temp_display erneut auf, um die aktualisierte Temperatur anzuzeigen
  5. Geben Sie die Fahrenheit-Umrechnung mit temp_to_fahrenheit aus

Geben Sie die Ergebnisse in diesem Format aus:

Current: {celsius}C
Current: {celsius}C
Fahrenheit: {fahrenheit}F

Verwenden Sie %.1f für alle Temperaturwerte, um eine Dezimalstelle anzuzeigen.

Zum Beispiel wäre bei einem Initialwert von 20.0 und einer Anpassung von 5.0 die Ausgabe:

Current: 20.0C
Current: 25.0C
Fahrenheit: 77.0F

Spickzettel

Das Schlüsselwort const kann bei Zeigerparametern verwendet werden, um anzugeben, dass eine Funktion die Daten, auf die gezeigt wird, nicht verändert. Dies wird als Const-Korrektheit bezeichnet.

Wenn ein Zeigerparameter als const markiert ist, verhindert der Compiler jegliche Änderungen an den Daten über diesen Zeiger:

typedef struct {
    int x;
    int y;
} Point;

// Nur-Lese-Funktion - kann den Punkt nicht verändern
void point_print(const Point *self) {
    printf("(%d, %d)\n", self->x, self->y);
    // self->x = 10;  // FEHLER: Änderung über const-Zeiger nicht möglich
}

// Modifizierende Funktion - kann den Punkt verändern
void point_move(Point *self, int dx, int dy) {
    self->x += dx;
    self->y += dy;
}

Die Verwendung von const Point *self signalisiert sowohl dem Compiler als auch anderen Programmierern, dass die Funktion eine Nur-Lese-Operation ist. Dies hilft, Fehler frühzeitig zu finden – wenn Sie versehentlich versuchen, Daten in einer Funktion zu ändern, die nichts verändern sollte, gibt der Compiler sofort einen Fehler aus.

Best Practice: Verwenden Sie const für Zeigerparameter, wann immer die Funktion die Daten nicht ändern muss. Dies macht die Absicht Ihres Codes klarer und verhindert versehentliche Änderungen.

Probier es selbst

#include <stdio.h>
#include "temperature.h"

int main() {
    double initial_celsius, adjustment;
    scanf("%lf", &initial_celsius);
    scanf("%lf", &adjustment);
    
    // TODO: Erstelle eine Temperature-Struktur und initialisiere sie mit initial_celsius
    
    // TODO: Rufe temp_display auf, um die Starttemperatur anzuzeigen
    
    // TODO: Rufe temp_adjust auf, um die Temperatur um den Anpassungsbetrag zu ändern
    
    // TODO: Rufe temp_display erneut auf, um die aktualisierte Temperatur anzuzeigen
    
    // TODO: Gib die Fahrenheit-Umrechnung mit temp_to_fahrenheit aus
    // Format: "Fahrenheit: %.1fF\n"
    
    return 0;
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Object Oriented Programming