Post on 15-Aug-2019
transcript
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 <stdio.h>
#include <stdlib.h>
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 <stdio.h>
#include <stdlib.h>
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 <stdio.h>
#include <stdlib.h>
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"