Menu
Coddy logo textTech

Pointer vs. Wert

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

Wenn Sie ein Struct an eine Funktion übergeben, bietet Ihnen C zwei Möglichkeiten: die Übergabe als Wert (Kopie des gesamten Structs) oder die Übergabe als Zeiger (Kopie nur der Adresse). Die Wahl ist für die Performance von großer Bedeutung.

Die Übergabe als Wert erstellt eine vollständige Kopie des Structs auf dem Stack. Für ein kleines Struct mit ein paar Integern ist das in Ordnung. Aber stellen Sie sich ein Struct mit hunderten von Bytes vor – jeder Funktionsaufruf kopiert all diese Daten:

typedef struct {
    char name[100];
    int scores[50];
    double average;
} Student;

// Wertübergabe: kopiert bei jedem Aufruf ~608 Bytes
void print_by_value(Student s) {
    printf("%s: %.2f\n", s.name, s.average);
}

// Zeigerübergabe: kopiert nur 8 Bytes (die Adresse)
void print_by_pointer(const Student *s) {
    printf("%s: %.2f\n", s->name, s->average);
}

Die Syntax unterscheidet sich ebenfalls. Bei einem Wertparameter verwenden Sie den Punkt-Operator (s.name). Bei einem Pointer verwenden Sie den Pfeil-Operator (s->name).

Die Pointer-Version ist effizienter, da sie nur eine Speicheradresse übergibt – typischerweise 8 Bytes, unabhängig von der Größe des Structs.

Das ist der Grund, warum C-Programmierer Structs fast immer per Pointer übergeben. Verwenden Sie const, wenn die Funktion die Daten nicht verändern soll, und einen regulären Pointer, wenn sie es soll. Sie erhalten sowohl Effizienz als auch eine klare Absicht.

challenge icon

Aufgabe

Einfach

Lassen Sie uns ein Product-Modul erstellen, das den Unterschied zwischen der Übergabe von Structs als Wert (by value) und als Zeiger (by pointer) demonstriert. Sie werden zwei Anzeige-Funktionen erstellen – eine, die das gesamte Struct als Kopie erhält, und eine, die nur einen Zeiger darauf erhält.

Sie werden drei Dateien erstellen:

  • product.h: Deklarieren Sie ein Product-Struct mit drei Elementen: char name[50], double price und int quantity. Deklarieren Sie außerdem zwei Funktionen:
    • display_by_value — nimmt ein Product als Wert entgegen und gibt dessen Informationen aus
    • display_by_pointer — nimmt einen const Product * entgegen und gibt dieselben Informationen aus
    Verwenden Sie Include-Guards mit dem Symbol PRODUCT_H.
  • product.c: Implementieren Sie beide Funktionen. Beachten Sie den Unterschied in der Syntax: Die "by-value"-Version verwendet den Punkt-Operator (p.name), während die Zeiger-Version den Pfeil-Operator (p->name) verwendet. Beide Funktionen sollten im gleichen Format drucken.
  • main.c: Erstellen Sie ein Product und rufen Sie dann beide Anzeige-Funktionen auf, um zu zeigen, dass sie trotz unterschiedlicher Parameterstile eine identische Ausgabe erzeugen.

Sie erhalten drei Eingaben: den Produktnamen (ein String), den Preis (ein Double) und die Menge (ein Integer).

Initialisieren Sie in Ihrer Hauptdatei ein Product mit diesen Werten und rufen Sie dann display_by_value gefolgt von display_by_pointer auf.

Beide Funktionen sollten in diesem Format drucken:

Product: {name}, Price: {price}, Qty: {quantity}

Verwenden Sie %.2f für den Preis, um zwei Dezimalstellen anzuzeigen.

Zum Beispiel wäre bei den Eingaben Laptop, 999.99 und 5 die Ausgabe:

Product: Laptop, Price: 999.99, Qty: 5
Product: Laptop, Price: 999.99, Qty: 5

Spickzettel

Beim Übergeben von Structs an Funktionen können Sie zwischen der Übergabe als Wert (Kopieren des gesamten Structs) oder der Übergabe als Zeiger (Kopieren nur der Adresse) wählen.

Die Übergabe als Wert erstellt eine vollständige Kopie des Structs:

void print_by_value(Student s) {
    printf("%s: %.2f\n", s.name, s.average);  // Punkt-Operator verwenden
}

Die Übergabe als Zeiger übergibt nur die Speicheradresse:

void print_by_pointer(const Student *s) {
    printf("%s: %.2f\n", s->name, s->average);  // Pfeil-Operator verwenden
}

Wichtige Unterschiede:

  • Bei der Übergabe als Wert wird der Punkt-Operator verwendet (s.member)
  • Bei der Übergabe als Zeiger wird der Pfeil-Operator verwendet (s->member)
  • Zeiger sind effizienter für große Structs (nur 8 Byte gegenüber der gesamten Struct-Größe)
  • Verwenden Sie const bei Zeigern, wenn die Funktion die Daten nicht verändern soll

C-Programmierer bevorzugen in der Regel die Übergabe von Structs per Zeiger, um eine bessere Performance zu erzielen.

Probier es selbst

#include <stdio.h>
#include <string.h>
#include "product.h"

int main() {
    char name[50];
    double price;
    int quantity;
    
    // Eingaben lesen
    scanf("%s", name);
    scanf("%lf", &price);
    scanf("%d", &quantity);
    
    // TODO: Erstelle eine Product Variable und initialisiere sie mit den Eingabewerten
    // Hint: Verwende strcpy, um den Namen in das name Feld des structs zu kopieren
    
    // TODO: Rufe display_by_value mit dem Product auf
    
    // TODO: Rufe display_by_pointer mit einem Zeiger auf das Product auf
    
    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