Teil 6: Strukturen und Unionen - fritzsch/Programmieren/Folien/Prog06.pdf · Kapitel 6: Strukturen...

of 34 /34
Gliederung Strukturen Typdefinitionen Unionen Dynamische Speicherverwaltung Teil 6: Strukturen und Unionen

Embed Size (px)

Transcript of Teil 6: Strukturen und Unionen - fritzsch/Programmieren/Folien/Prog06.pdf · Kapitel 6: Strukturen...

  • Gliederung

    Strukturen

    Typdefinitionen

    Unionen

    Dynamische Speicherverwaltung

    Teil 6: Strukturen und Unionen

  • Kapitel 6: Strukturen und Unionen

    Strukturen Typdefinitionen Unionen Dynamische Speicherverwaltung

    6.2

    Strukturen

  • Kapitel 6: Strukturen und Unionen

    Strukturen Typdefinitionen Unionen Dynamische Speicherverwaltung

    6.3

    Strukturen

    � Ursprung in Pascal als Datentyp record, Verbunddatentyp

    � Strukturtyp in C

    � kann Komponenten (Variablen) verschiedener Typen enthalten:

    � Anwendung: Gruppierung logisch zusammenhängender Daten z. B. Datum, Adresse, Personendaten, geometrische Objekte, .

    � Behandlung beim Lesen und Schreiben immer als als Einheit

    Personal- Nachname Vorname Straße Haus- Postleit- Wohnort Gehalt nummer nummer zahl

    int char[20] char[20] char[20] int int char[20] float

  • Kapitel 6: Strukturen und Unionen

    Strukturen Typdefinitionen Unionen Dynamische Speicherverwaltung

    6.4

    Strukturtyp-Definition

    � frei definierter, zusammengesetzter Datentyp

    � feste Anzahl von Komponenten

    struct Name

    {

    typ1 komponentenVariable_1;

    typ2 komponentenVariable_2;

    . . .

    typN komponentenVariable_n;

    };

    � der Typname ist struct Name

  • Kapitel 6: Strukturen und Unionen

    Strukturen Typdefinitionen Unionen Dynamische Speicherverwaltung

    6.5

    Strukturvariablen-Definition

    � Variable eines Strukturtyps = aus Komponentenvariablen zusammengesetzte Variable

    � Erstellung einer Variablen des Typs struct Name

    struct Name variable;

    Komponenten- variable 1

    Komponenten- variable 2

    Komponenten- variable n ...

    Strukturvariable

  • Kapitel 6: Strukturen und Unionen

    Strukturen Typdefinitionen Unionen Dynamische Speicherverwaltung

    6.6

    Beispiel-Definition

    struct Adresse

    {

    char strasse[20];

    int hausnummer;

    int postleitzahl;

    char stadt[20];

    };

    struct Student

    {

    int matrikelnummer;

    char name[20];

    char vorname[20];

    struct Adresse wohnort;

    };

    struct Student meyer, mueller; // 2 Studenten

    struct Student semester[50]; // Feld aus 50 Studenten

  • Kapitel 6: Strukturen und Unionen

    Strukturen Typdefinitionen Unionen Dynamische Speicherverwaltung

    6.7

    Übergabe an Funktionen

    � call-by-value (wie bei elementaren Datentypen int, float, etc.)

    Initialisierungslisten

    struct Student student1 =

    {

    66202,

    "Meyer",

    "Herbert",

    {

    "Schillerplatz",

    20,

    73730,

    "Esslingen"

    }

    };

  • Kapitel 6: Strukturen und Unionen

    Strukturen Typdefinitionen Unionen Dynamische Speicherverwaltung

    6.8

    Zugriff auf Komponentenvariablen

    student1.matrikelnummer = 716347;

    struct Wort

    {

    char s[20];

    }

    struct Wort w1, w2;

    char c1[20], c2[20];

    strcpy(c1, "Hallo");

    strcpy(w1.s, "Hallo");

    c2 = c1;

    w2 = w1;

    strcpy(c2, c1); /* RICHTIG */

    /* RICHTIG, eine Struktur ist ein L-Value */

    /* FALSCH, ein Feld ist kein L-Value */

  • Kapitel 6: Strukturen und Unionen

    Strukturen Typdefinitionen Unionen Dynamische Speicherverwaltung

    6.9

    Zugriff auf Komponentenvariablen

    student1.matrikelnummer = 716347;

    strcpy (student1.name, "Meyer");

    student1.wohnort.postleitzahl = 73733;

    strcpy (student1.wohnort.stadt, "Esslingen");

    printf ("%6d %5d %s\n", student1.matrikelnummer,

    student1.wohnort.postleitzahl,

    student1.name);

  • Kapitel 6: Strukturen und Unionen

    Strukturen Typdefinitionen Unionen Dynamische Speicherverwaltung

    6.10

    Kombination von Typ- und Variablendefinition

    � ohne Strukturname/Etikett (unüblich)

    struct

    {

    float x;

    float y;

    } punkt1, punkt2, punkt3;

    � mit Strukturname/Etikett (üblich)

    struct Koordinaten

    {

    float x;

    float y;

    } punkt1, punkt2, punkt3;

    struct Koordinaten punkt4, punkt5, punkt6;

  • Kapitel 6: Strukturen und Unionen

    Strukturen Typdefinitionen Unionen Dynamische Speicherverwaltung

    6.11

    Struktur-Zuweisungen, Vergleich

    � direkte Zuweisung möglich, alle Komponentenwerte der Variablen punktAwerden den jeweiligen Komponenten der Variablen punkt3 zugewiesen

    struct Koordinaten punktA = {1.5, 3.0}, punktB;

    punktB = punktA;

    � ABER: Prüfung auf Gleichheit if (punktA == punktB) ist nicht möglich!

    � Bestimmung der Größe in Bytes einer Strukturvariablen:

    sizeof (struct Koordinaten)

  • Kapitel 6: Strukturen und Unionen

    Strukturen Typdefinitionen Unionen Dynamische Speicherverwaltung

    6.12

    Selektion über Zeiger

    � Punktoperator . und Pfeiloperator ->

    struct Koordinaten

    {

    float x;

    float y;};

    struct Koordinaten punktA = {1.5, 3.0}, *ppunkt;

    ppunkt = &punktA;

    � Wie greife ich auf Komponenten von punktA über den Zeiger ppunkt zu?

    � Komponenten-Selektion über Zeiger auf 2 Arten möglich:

    (*ppunkt).x bzw. ppunkt->x

    (*ppunkt).x = 3; ppunkt->x = 3;

  • Kapitel 6: Strukturen und Unionen

    Strukturen Typdefinitionen Unionen Dynamische Speicherverwaltung

    6.13

    Zeiger und geschachtelte Strukturen

    � Strukturvariablen als Komponenten

    struct Vektor

    {

    struct Koordinaten *anfang;

    struct Koordinaten *ende;};

    � Zeiger vom Typ Vektor

    struct Vektor vec, *pvec;

    vec.anfang = &punkt2;

    vec.ende = &punkt3;

    pvec = &vec;

    ...

    pvec->anfang->x bzw.

  • Kapitel 6: Strukturen und Unionen

    Strukturen Typdefinitionen Unionen Dynamische Speicherverwaltung

    6.14

    Strings in Strukturen

    � String als Komponentenvariable

    struct Name

    {

    char nachname[20];

    char *vorname;

    };

    struct Name person1 = {"Maier", "Herbert"};

    � char nachname[20]; strukturintern, String gehört zur Strukturvariablen

    � char *vorname; strukturextern, (in diesem Falle konstanter String)

  • Kapitel 6: Strukturen und Unionen

    Strukturen Typdefinitionen Unionen Dynamische Speicherverwaltung

    6.15

    Typdefinition mit typedef

  • Kapitel 6: Strukturen und Unionen

    Strukturen Typdefinitionen Unionen Dynamische Speicherverwaltung

    6.16

    Was ist typedef?

    � Vergabe eines neuen Namens (Alias) neuername für einen

    • schon bekannten oder

    • soeben definierten Datentyp

    typedef bekanntertyp neuername;

    � Beispiele: typedef unsigned long int UINT;

    UINT a;

    typedef float REAL;

    REAL b;

  • Kapitel 6: Strukturen und Unionen

    Strukturen Typdefinitionen Unionen Dynamische Speicherverwaltung

    6.17

    Anwendung

    � spart Schreibarbeit

    � Portierbarkeit von Programmen mit maschinenabhängigen Datentypen(maschinenabhängige Datentypen treten NUR in der typedef Zeile auf)

    � Beispiel: Windows-API

    https://msdn.microsoft.com/en-

    us/library/windows/desktop/aa383751%28v=vs.85%29.aspx

  • Kapitel 6: Strukturen und Unionen

    Strukturen Typdefinitionen Unionen Dynamische Speicherverwaltung

    6.18

    Anwendung

    � Beispiel: einheitlicher Long-Integer LINT

    typedef long long int LINT; // Anpassung auf LLP64-System

    typedef long int LINT; // Anpassung auf LP64-System

  • Kapitel 6: Strukturen und Unionen

    Strukturen Typdefinitionen Unionen Dynamische Speicherverwaltung

    6.19

    typedef und Strukturen

    struct Datum

    {

    short int tag;

    char monat[10];

    short int jahr;

    };

    struct Datum heute;

    Empfohlene Variante

    typedef struct

    {

    short int tag;

    char monat[10];

    short int jahr;

    } DATUM;

    DATUM heute;

  • Kapitel 6: Strukturen und Unionen

    Strukturen Typdefinitionen Unionen Dynamische Speicherverwaltung

    6.20

    Unionen

  • Kapitel 6: Strukturen und Unionen

    Strukturen Typdefinitionen Unionen Dynamische Speicherverwaltung

    6.21

    Union-Definition

    � Benutzung wie Struktur

    � ABER: alle Komponenten (Alternativen) beginnen bei der selben Adresse

    � speichert jeweils nur eine einzige Komponente (aus Reihe von Alternativen)

    � Programmierer ggf. muss verfolgen, welcher Typ momentan in der Union gespeichert ist

    union Variant

    {

    int intAlternative;

    float floatAlternative;

    };

  • Kapitel 6: Strukturen und Unionen

    Strukturen Typdefinitionen Unionen Dynamische Speicherverwaltung

    6.22

    Zugriff auf Alternativen

    union Variant

    {

    int intAlternative;

    float floatAlternative;

    };

    int x;

    union Variant vario;

    � Alternative schreiben / auslesen

    vario.floatAlternative = 123.0;

    x = vario.intAlternative;

    � Zeiger auf Union

    union Variant *pVario = &vario;

    x = pVario->intAlternative;

  • Kapitel 6: Strukturen und Unionen

    Strukturen Typdefinitionen Unionen Dynamische Speicherverwaltung

    6.23

    Beispiel: Prozessorregister

    struct WORDREGS

    {

    unsigned int ax;

    unsigned int bx;

    unsigned int cx;

    unsigned int dx;

    };

    struct BYTEREGS

    {

    unsigned char al,ah;

    unsigned char bl,bh;

    unsigned char cl,ch;

    unsigned char dl,dh;

    };

    union REGS

    {

    struct WORDREGS w;

    struct BYTEREGS b;

    };

    inregs.w.ax = 0x0815; /* BX Register auf Hex 0815 setzen */

    inregs.b.ch = 0x1A; /* AH Register auf Hex 1A setzen */

    union REGS inregs;

  • Dynamische Speicherverwaltung

  • Kapitel 6: Strukturen und Unionen

    Strukturen Typdefinitionen Unionen Dynamische Speicherverwaltung

    6.26

    Dynamische Speicherverwaltung

    Problem: Speicherbedarf ist während verschiedenerProgrammausführungen unterschiedlich

    Lösung: Variablen (insb. Arrays) maximal dimensionieren:

    char eingabetext[1000];

    Variable Feldgröße in lokalen Arrays nutzen (ab C99)

    � Nachteile?

  • Kapitel 6: Strukturen und Unionen

    Strukturen Typdefinitionen Unionen Dynamische Speicherverwaltung

    6.27

    Statische vs. dynamische Variablen

    � statische Variable (inkl. lokal, global)

    int x;

    Verfügbarkeit und Ablage/Speichersegment je nach Speicherklasse (auto, register, static, extern)

    � Speichersegmente

    Code

    Daten

    Heap

    Stack

    lokale

    Variable

    globale

    Variable

  • Kapitel 6: Strukturen und Unionen

    Strukturen Typdefinitionen Unionen Dynamische Speicherverwaltung

    6.28

    Statische vs. dynamische Variablen

    � dynamische Variable hat keinen Bezeichner, keine Vereinbarung

    � Anlegen erfolgt bei Bedarf auf dem Heap

    � Zugriff durch Zeiger auf Bereich im Heap

    Daten

    Stack

    Heap

    stat. Pointer-Variable

    stat. Pointer-Variable

    dyn. Variable

    dyn. Variable

    Code

    Daten

    Heap

    Stack

    lokale

    Variable

    globale

    Variable

  • Kapitel 6: Strukturen und Unionen

    Strukturen Typdefinitionen Unionen Dynamische Speicherverwaltung

    6.29

    Dynamische Speicherverwaltung

    Problem: Speicherbedarf ist während verschiedenerProgrammausführungen unterschiedlich

    Lösung bisher: Variablen (insb. Arrays) maximal dimensionieren � Nachteil: "verschenkter" Speicher

  • Kapitel 6: Strukturen und Unionen

    Strukturen Typdefinitionen Unionen Dynamische Speicherverwaltung

    6.30

    Dynamische Speicherverwaltung

    Problem: Speicherbedarf ist während verschiedenerProgrammausführungen unterschiedlich

    Lösung bisher: Variablen (insb. Arrays) maximal dimensionieren � Nachteil: "verschenkter" Speicher

    stdlib.h bietet Funktionen zum Speicheranforderung und -freigabe:

    void* malloc(int Groesse);

    void* calloc(int AnzahlElemente, int ElementGroesse);

    void* realloc(void *memBlock, int Groesse);

    void free(void *memBlock);

    Lösung neu: Speicherbedarf dynamisch, d.h. zur Programmlaufzeitfestlegen

  • Kapitel 6: Strukturen und Unionen

    Strukturen Typdefinitionen Unionen Dynamische Speicherverwaltung

    6.31

    Speicherreservierung mit malloc()

    #include

    #include

    int main()

    {

    int *pMem;

    pMem = malloc(sizeof (int));

    if (p != NULL)

    {

    *pMem = 3;

    printf("pointer auf int-Zahl mit Wert: %d\n", *pMem);

    free(pMem);

    }

    else

    printf("Speicheranforderung fehlgeschlagen.\n");

    return 0;

    }

  • Kapitel 6: Strukturen und Unionen

    Strukturen Typdefinitionen Unionen Dynamische Speicherverwaltung

    6.32

    Speicherreservierung mit realloc() I

    #include

    #include

    int main()

    {

    int *pMem;

    pMem = malloc(sizeof (int));

    if (pMem == NULL)

    {

    printf("Speicheranforderung fehlgeschlagen.\n");

    return -1;

    }

    *pMem = 3;

    printf("Nach malloc():\n");

    printf("pointer auf int-Zahl mit Wert: %d\n", *pMem);

    ...

  • Kapitel 6: Strukturen und Unionen

    Strukturen Typdefinitionen Unionen Dynamische Speicherverwaltung

    6.33

    Speicherreservierung mit realloc() II

    ...

    pMem = realloc ((void *)pMem, 2 * (sizeof(int)));

    if (pMem == NULL)

    {

    printf ("Speicheranforderung fehlgeschlagen.\n");

    return -1;

    }

    pMem[0] = 4;

    pMem[1] = 6;

    printf("Nach realloc():\n");

    printf("1. Element von pMem hat den Wert: %d\n", pMem[0]);

    printf("2. Element von pMem hat den Wert: %d\n", pMem[1]);

    free(pMem);

    return 0;

    }

  • Kapitel 6: Strukturen und Unionen

    Strukturen Typdefinitionen Unionen Dynamische Speicherverwaltung

    6.34

    Speicherreservierung für ein Feld

    #include

    #include

    int main()

    {

    int *pArray = NULL;

    int i, anzahl = 0;

    printf "Geben Sie die Anzahl der Feld-Elemente ein: ");

    scanf("%d", &anzahl);

    pArray = malloc(anzahl * sizeof(int));

    if (pArray == NULL)

    return -1;

    // Nutzung des reservierten Speicherbereichs

    for (i = 0; i < anzahl; i++)

    pArray[i] = i * i;

    ...

    free(pArray);

    return 0;

    }

  • Kapitel 6: Strukturen und Unionen

    Strukturen Typdefinitionen Unionen Dynamische Speicherverwaltung

    6.35

    malloc & free: Typische Fehler

    Fehler Folge

    1) kein Speicher mehr frei2) Freigabe einer falschen Adresse u.U. Absturz3) Freigabe bereits freigegeben Speichers u.U. Absturz4) Freigabe eines regulären Feldes /

    einer regulären Variablen mit free() u.U. Absturz5) Freigabe eines nicht-initialisierten Speichers u.U. Absturz6) Zugriff auf ungültigen Speicher vor der

    Speicheranforderung u.U. Absturz7) Zugriff auf bereits freigegebenen Speicher u.U. Absturz8) Zugriff auf Speicher mit ungültigen Indizes u.U. Absturz9) Verlust des Speichers durch Überschreiben

    des Zeigers "memory leak"10) Verlust des Zeigers durch Rücksprung aus

    einer Funktion "memory leak"11) Verlust des Zeigers bei Rückgabe

    (return-value verworfen) "memory leak"