Te chnische Infor matik 2 C/C++-K urs Pointer und Arrays(Teil 2) …+/3.pdf · 2005-10-09 · Te...
Transcript of Te chnische Infor matik 2 C/C++-K urs Pointer und Arrays(Teil 2) …+/3.pdf · 2005-10-09 · Te...
Technische Infor matik 2C/C++-Kurs
Pointer und Arrays (Teil 2)
Referenzen
© 2005 AG Rechner netze 3.1
Pointer und Arrays
• Pointer-Arrays, Pointer auf Pointer
– Pointer-Array-Deklaration
char *names[12];
– Definition mit Initialisierung (nur für globale Var iablen)
char *names[] = { "Januar", "Februar", "Maerz", "April", "Mai", ...};
– Pointer-Array degener iert zu Pointer auf Pointer in Ausdrücken
char **ptr = names;
– Schleife über Pointer-Array mit Index:
int i;
for (i = 0; i < 12; i++)
cout << names[i] << endl;
– Pointer-Version:
char **p;
for (p = names; p < names+12; p++)
cout << *p << endl;
© 2005 AG Rechner netze 3.2
Pointer und Arrays
– Zeilen in Array einlesen:
int readlines(char **lines, int maxlines) {
int n = 0;
char line[MAXLEN];
while (cin.getline(line, MAXLEN)) {
// cin.gcount() includes \n → \0
char *p = new char[cin.gcount()];
if (n >= maxlines || p == 0)
return −1;strcpy(p, line);
lines[n++] = p;}
return n;}
• Unschön: diese Funktion hat ein Speicherleck! Besser die if-Bedingung inzwei Abfragen aufteilen und den Speicher u.U. wieder freigeben
© 2005 AG Rechner netze 3.3
Pointer und Arrays
– Zeilen ausgeben:
void writelines(char **lines, int n) {
while (n−− > 0)
cout << *lines++ << endl;}
– Benutzung:
char *buf[100];
nlines = readlines(buf, 100);
writelines(buf, nlines);
• Argumente aus Kommandoz eile
– main wird mit Argumenten aus Kommandozeile aufgerufen
int main(int argc, char *argv[]);
– Erstes Argument Anzahl der Argumente
– Zweites Argument Array mit Strings
– argv[0] ist Programmname (argc mindestens 1)
© 2005 AG Rechner netze 3.4
Pointer und Arrays
– Beispiel: Shell-Kommando echo(1):
/* echo [−n] [arg...] */
int main(int argc, char **argv) {
bool nflag = false;
if (argc > 1 && argv[1][0] == ’−’&& argv[1][1] == ’n’) {
nflag = true;
argc−−; argv++;
}
while (−−argc > 0)cout << *++argv << (argc > 1 ? " " : "");
if (!nflag)
cout << endl;
return 0; /* oder exit(0); */
}
© 2005 AG Rechner netze 3.5
Pointer und Arrays
• Funktionspointer
– Deklaration von Funktionspointern
int (*p)(int); char *(*q)();
– Zuweisung an Funktionspointer, Aufr uf
int add(int a, int b) {
return a + b;
}
...
int i, (*f)(int, int);
f = &add;
i = (*f)(1, 2);
void (*strfun)(char *, char *);
strfun = &strcpy;
© 2005 AG Rechner netze 3.6
Pointer und Arrays
– & und * können weggelassen werden:
f = add; entspr icht f = &add;
i = f(1, 2); entspr icht i = (*f)(1, 2);
strfun = strcpy; entspr icht strfun = &strcpy;
– typedef und Funktionspointer
typedef void (*Strfunc)(char *, char *);
Strfunc strfun = strcpy;;
© 2005 AG Rechner netze 3.7
Pointer und Arrays
• komplexeres Beispiel
– ANSI-C Librar y-Funktion Quicksor t:
void qsort(void *base, int nelem, int size,
int (*compare)(const void *, const void *));
• base zu sortierendes Array, nelem Elemente
• size Größe eines Elements
• compar benutzerdefinier te Vergleichsfunktion
– Beispiel für qsort-Benutzung (Strings sortieren):
int compstr(const void *p, const void *q) {
return strcmp(*(char **)p, *(char **)q);
}
void main(int argc, char **argv) {
qsort((void *)++argv, −−argc, sizeof(char *), compstr);while(argc−− > 0)
cout << *argv++ << endl;
}
© 2005 AG Rechner netze 3.8
Pointer und Arrays
• Mehrdimensionale Arrays
– Werden in C selten benutzt
– Häufiger : Pointer-Arrays
– Deklaration 2-dimensionales Array:
int i[2][10];
• Deklar iert Array mit 2 Elementen
• Jedes Element ist Array von 10 ints
• Erster Index Zeile, zweiter Index Spalte
• ⇒ i[0][0] i[0][1] ... i[0][9] i[1][0] ...
– Initialisier ung:
int matrix[2][5] = { char *days[][7] = {
{ 2, 5, 0, 0, 1 }, { "Monday", "Tuesday", ... },
{ 0, 9, 1, 2, 4 } { "Montag", "Dienstag", ... }
}; };
© 2005 AG Rechner netze 3.9
Pointer und Arrays
• Mehrdimensionale Arrays als Argumente
– Beispiel:
void f(int a[2][10]) { ... }
– Anzahl der Zeilen kann weggelassen werden:
void f(int a[][10]) { ... }
– Deklaration als Pointer :
void f(int (*a)[10]) { ... }
– a ist Pointer auf Array von 10 ints
– Achtung, nicht verwechseln mit:
int *a[10]; /* Array von 10 Pointern */
© 2005 AG Rechner netze 3.10
Pointer und Arrays
• Mehrdimensionale Arrays und Pointer
– Array wird zu Pointer auf erstes Element in Expression (Pointer auf Array)
int mat[2][10];
int (*p)[10];
p = mat; /* oder: p = &mat[0]; */
– Durchlaufen einer Zeile mit Pointer :
int *col;
for (col = p[1]; col < p[1] + 10; col++)
cout << *col << " ";
– Frage: was passiert bei p++?
© 2005 AG Rechner netze 3.11
Strukturen
• Strukturen
– Deklaration von Strukturen (definiert Typ):
struct point {
int x;
int y;};
struct rectangle {
point p1, p2;
// In C: struct point p1, p2;};
struct employee {
char *name, *address;
double salary;
char office[10];};
– Definition von Struktur-Var iablen:
point pt;
point maxpt = { 1024, 950 };
© 2005 AG Rechner netze 3.12
Strukturen
– Name in Strukturdeklaration optional:
struct { ... } var, *ptr;
– Zugriff auf Komponenten einer Struktur :
point p; rectangle r;
p.x = 300; p.y = 500; r.p1.x = p.x;
– Pointer auf Strukturen
point origin, *pp;
pp = &origin;
cout << "origin: " << (*pp).x << "," << (*pp).y;
– Abkürzende Schreibweise:
cout << "origin: " << pp−>x << "," << pp−>y;
© 2005 AG Rechner netze 3.13
Strukturen
• Arrays von Strukturen
struct key {
char *word;
int count;
};
key keytab[nkeys];
– Deklaration mit Initialisierung:
struct key {
char *word; int count;
};
key keytab[] = {
"break", 0,
"case", 0,
"char", 0,
...
"while", 0
};
© 2005 AG Rechner netze 3.14
Strukturen
– Beispiel: Zählen von Keywords in Eingabe:
main() {
int n;
char word[MAXWORD];
while (readword(word, MAXWORD))
if (*word >= ’a’ && *word <= ’z’ &&
(n = search(word, keytab, nkeys)) >= 0)
keytab[n].count++;
for (n = 0; n < nkeys; n++)
if (keytab[n].count > 0)
cout << keytab[n].count << " "
<< keytab[n].word << endl;}
– Array-Loop mit Pointer :
key *p;
for (p = keytab; p < keytab + nkeys; p++)
if (p−>count > 0)
cout << p−>count << " " << p−>word << endl;
© 2005 AG Rechner netze 3.15
Strukturen
– Automatische Berechnung der Tabellengröße:
const int nkeys = sizeof keytab / sizeof(key);
const int nkeys = sizeof keytab / sizeof *keytab;
– sizeof-Operator, allgemeine For m:
sizeof Objekt sizeof(Typ-Name)
• Selbst-referenzierende Strukturen
– Beispiel: einfach ver kettete Liste
struct node {
char *word;
node *next;
};
© 2005 AG Rechner netze 3.16
Strukturen
struct node {
char *word;
node *next;
};
char word[MAXWORD];
node *list = 0;
while (readword(word, MAXWORD) != EOF) {
node *p = new node; // Ouch (== 0?)
p−>word = strdup(word);
p−>next = list;
list = p;}
for (node *p = list; p; p = p−>next) cout << p−>word << endl;
for (node *p = list; p; ) {
delete[] p−>word;
node *q = p−>next;
delete p;
p = q;}
© 2005 AG Rechner netze 3.17
Strukturen, Unions
• Unions
– Zugriff auf Objekte verschiedenen Typs
• Objekte liegen an derselben Speicheradresse
– Union ist für Leute, die sich nicht entscheiden können
– Union-Deklaration syntaktisch wie Struktur :
union obj {
int ival;
float fval;
} u, *ptr;
u.ival = 5;
ptr = &u;
i = ptr−>ival;
© 2005 AG Rechner netze 3.18
Strukturen, Unions
– Semantik ähnlich Struktur
• alle Komponenten Offset 0
• Größe wird durch größtes Feld bestimmt
• Alignment passend für alle Typen in Union
– Union-Initialisier ung (erstes Feld)
union {
int i;
float f;
} u = { 4711 };
© 2005 AG Rechner netze 3.19
Strukturen, Unions
• Unions und Strukturen
– Unions sind oft Bestandteil von Strukturen
– Str uktur-Komponente ver merkt aktuellen Typ in Union
enum Type { FLOAT, STRING };
struct Object {
enum Type type;
union {
float f;
char *s;
} u;};
Object x, y;
x.type = FLOAT; y.type = STRING;
x.u.f = 3.141592; y.u.s = "hello";
switch (x.type) {
case FLOAT: do_float(x.u.f); break;
case STRING: do_string(x.u.s); break;
}
© 2005 AG Rechner netze 3.20
Strukturen, Unions
• Anonyme Unions
– C-Syntax schwerfällig
– C++: Anonyme Unions verschmelzen mit Strukturenum Type { FLOAT, STRING };
struct Object {
enum Type type;
union { // Kein Typname
float f;
char *s;
}; // Kein Feldname};
Object x, y;
x.type = FLOAT; y.type = STRING;
x.f = 3.141592; y.s = "hello";
switch (x.type) {
case FLOAT: do_float(x.f); break;
case STRING: do_string(x.s); break;
}
© 2005 AG Rechner netze 3.21
Strukturen, Unions
• Bit-Fields
– Packen mehrerer Objekte in ein Wor t
• Spar t Speicher platz
• Nützlich bei Schnittstellen zur Hardware
– Deklaration als Struktur-Felder :
struct employee {
unsigned int is_female : 1;
unsigned int is_married : 1;
unsigned int num_children : 5;
unsigned int age : 6;
};
employee e;
e.is_female = 1;
e.num_children = 3;
– High-Order-Bit kann Vorzeichenbit sein (wenn signed)
– Bit-Field ohne Typ und Name für Padding
© 2005 AG Rechner netze 3.22
Referenztypen
• Referenz en: selbstdereferenzierende Pointer
– Initialisier ung mit Objekt
– Danach „Referenz“ konstant
int i = 17, j = 28;
int &falsch; // FEHLER: uninitialisiert
int &ir = i; // ir jetzt Alias für i
ir = 12; // i ist jetzt 12
ir = j; // i ist jetzt 28
int *ip = &ir; // ip ist jetzt &i
int &ir2 = ir; // ir2 ist jetzt Alias für i
– Konstante Referenzen: Auch Daten konstant
const int &cir = i;
cir = 19; // FEHLER: cir ist konstant
ir = 19; // i, ir, cir alle jetzt 19
const int ci = 4711;
const int &cir2 = ci;
int &ir3 = ci; // FEHLER: ci ist konstant
© 2005 AG Rechner netze 3.23
Referenztypen
• Call-by-reference
– Parameterübergabe ist auch Initialisierung
void swap(int& i, int& j) {
int t = i;
i = j;
j = t;}
int n, m;
swap(n, m);
– Referenzparameter für
• Ausgabe- und Ein-/Ausgabeparameter
• Übergabe von großen Daten
struct Huge {
double my_data[1048576];
};
double mean(const Huge&);
– const-Deklaration macht Eingabe deutlich
© 2005 AG Rechner netze 3.24
Referenztypen
• Return-by-reference
– Auch Rückgabewerte können Referenzen sein
int& index(int *p, int i) {
return p[i];
}
int a[10];
int i = index(a, 5);
index(a, 6) = i;
– Konstante Referenzen: z.B. für Rückgabe größerer Objekte ohneSchreibrecht
const Huge& find_right_huge();
© 2005 AG Rechner netze 3.25