~za08gywo

Übung 01 - Speicherverwaltung

Published at 08.05.2025

Manual-Pages

Mit dem Programm man kann die Dokumentation von verschiedenen Bibliotheksfunktionen nachgelesen werden: man 3p printf

Oft findet ihr die schreibweise time(3p), d.h. es wird auf die manpage von time aus der section 3p verwiesen: man 3p time

Workflow mit git

  • git clone [URL] - Remote Repo lokal herunterladen
  • git pull - Neuester Stand eines Repos herunterladen
  • git status - Mehr infos über das Repo bekommen
  • git add [FILE] - Änderungen zu stagen
  • git diff --staged . - Staged Änderungen nachvollziehen
  • git commit -m "[COMMMIT_MESSAGE]" - Änderungen zu dem Repo committen
  • git push - Neue Commits an das remote Repo kommunizieren (wichtig zur Übungsabgabe)

Die C Programmiersprache

  • Die "main" funktion in C bekommt immer 2 argumente:
    • int argc: enthält 1 + die Anzahl der Argumente, die dem Program gegeben wurden
    • char *argv[]: ein array von char-pointern (also ein char-pointer-pointer)
  • Das ende von char-arrays (string) wird mit dem Zeichen '\0' gekennzeichnet
  • Array-Zugriff: arr[1] ist gleichbedeutend mit *(arr + 1)
  • Struct-Zugriff: myStruct->value ist gleichbedeutend mit (*myStruct).value
  • Nützliches Pointer Diagramm

Fehlerbehandlung (wichtig)

Funktionen können in C fehlschlagen und fehler müssen immer abgefangen und behandelt werden (außer in einer bereits laufenden Fehlerbehandlung).

Was der Rückgabewert einer Funktion ist, wenn sie fehlschlägt, steht in dem "RETURN VALUE" Abschnitt der zugehörigen manpage. z.B. steht in malloc(3p), dass im Fehlerfall ein "null pointer" returned wird; Wir müssen uns also nach jedem malloc-Aufruf versichern, dass der Rückgabewert nicht ein null pointer war:

#include <stdlib.h>

int main(int argc, char *argv[]) {
  // wir wollen 5 ints abspeichern
  int *p = malloc(sizeof(int) * 5);
  if (p == NULL) {
    // es gab einen fehler
    return -1;
  }
  // kein fehler -> es kann weitergemacht werden ...
}

malloc und free

Wichtig ist, dass mit malloc allokierter speicher auch wieder manuell mit der Funktion free() freigegeben werden muss (free() kann nicht fehlschlagen und benötigt so auch keine Fehlerbehandlung):

#include <stdlib.h>

int main(int argc, char *argv[]) {
  int *p = malloc(sizeof(int) * 5);
  if (p == NULL) {
    return -1;
  }

  // ... do something with p ...

  free(p);
}

Beispiel Programme aus der Präsenzübung

Alle dem Program gegebenen Argumente drucken

#include <stdio.h>

int main(int argc, char *argv[]) {
  // iterate over arguments passed to program
  for (int i = 1; i < argc; i++) {
    // get reference to char-array for given argument
    char *curr_arg = argv[i]; 

    // alternative schreibweise:
    // char *curr_arg = *(argv + i);
    
    printf("%s\n", curr_arg);
  }
}

Jeden char der Argumente auf eine eigene Zeile drucken

Bei diesem Program wurde benutzt, dass in C, char-arrays mit einem '\0'-byte terminiert sind

#include <stdio.h>

int main(int argc, char *argv[]) {
  // iterate over arguments passed to program
  // start at i = 1, because i = 0 is the name of the program
  for (int i = 1; i < argc; i++) {
    // get reference to char-array for given argument
    char *curr_arg = argv[i];

    // iterate over the current argument, until '\0' is reached (end of string)
    int l = 0;
    while (curr_arg[l] != '\0') {
      printf("%c\n", curr_arg[l]);
      l++;
    }
  }
}

Speicher für structs anlegen

#include <stdlib.h>

struct listelement {
  int value;
  struct listelement *next;
};

int main(int argc, char *argv[]) {
  struct listelement *element1 = malloc(sizeof(struct listelement));
  if (element1 == NULL) {
    // fehlerbehandlung ...
  }

  // ... rest vom program

  free(element1);
}