Betriebs- und Kommunikationssysteme, 22./23.10.2015

Hinweise zur Übung 4

Definition von Structs

Der folgende Codeausschnitt definiert ein Struct (also eine Art Container, in diesem Fall für ganzzahlige 2d-Punkte) und tut gleich mehrere Sachen auf einmal.

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

Wir können den Code in die folgenden zwei Teile aufteilen:

// 1. Struct definieren
struct point {
    int x;
    int y;
};

// 2. Kurzen Namen geben
typedef struct point point;

Würden wir nur den ersten Teil schreiben, so muss danach bei jeder Verwendung von Variablen dieses Struct-Typs struct point variable geschrieben werden. Durch die typedef-Definition wird jede Verwendung von point implizit durch struct point ersetzt und wir sparen uns viel sinnlose Tipparbeit. Der zuerst gezeigte Code tut nichts anderes, als beides auf einmal zu tun, siehe auch Wikipedia (en).

Lest euch außerdem mal den letzten Absatz vor Unions in diesem Tutorial durch, es könnte hilfreich sein.

Anlegen von Struct-Instanzen

Möchtet ihr jetzt neue Instanzen von Structs anlegen geht das auf zwei verschiedene Arten, ähnlich dem, was wir heute für Strings im Tutorium gesehen haben. Entweder braucht ihr ein Objekt nur lokal, dann könnt ihr das einfach implizit auf dem Stack erzeugen.

void bar() {
    point p;
    p.x = 10;
    p.y = -45;
}

Wollt ihr neu erzeugte Objekte aber zurückgeben (oder generell auch außerhalb oder nach Beendigung der Funktion verwenden), tritt das gleiche Problem wie bei Strings auf, dass das Objekt auf dem Stack irgendwann überschrieben wird. Hier ist es also nötig, Speicher außerhalb des Stacks vom Betriebssystem anzufordern. Dies funktioniert (u.a.) über die Funktion malloc, welcher die Anzahl an Bytes übergeben werden muss, die wir benötigen. Um diese herauszufinden, verwenden wir den Operator sizeof.

point* bar() {
    point* p = malloc(sizeof point);
    p->x = 10;
    p->y = -45;
    return p;
}

void main() {
    point* test = bar();
    // Mach was tolles
    free(test);
}

Diese Variable muss nun, wenn sie nicht mehr verwendet wird, explizit gelöscht werden. Dies passiert mittels free.

Wie ihr auch sehen könnt, gibt es einen Unterschied, wie auf die Variablen innerhalb einer Struct-Variable zugegriffen wird. Ist die Variable ein Zeiger, so greifen wir mittels obj->var zu, ist es ein direktes “Objekt”, so passiert der Zugriff mittels obj.var.