1 Theorie | |
→ | 1.1 Die Programmiersprache C |
Ein Feld (engl. array) ist eine Folge von mehreren Elementen gleichen Typs.
Ein Feld wird mit
Typ Name[Größe];
definiert. Die Größe gibt die Anzahl der Elemente an.
Beispiel: Bei einer Temperaturmessung über 3 Stunden sollen minütlich Werte gemessen und abgespeichert werden, hierfür kann ein Feld mit
double temperatur[180];
angelegt werden.
Ein Feld kann auch durch eine Liste mit den Initialisierungswerten angegeben werden, z.B. enthält das Feld
int notenliste[] = { 1, 5, 3, 2, 1, 2, 2, 3 };
die Noten von 8 Studierenden.
Name[Index]
Auf Feldelemente wird zugegriffen, indem
nach dem Namen des Feldes in eckigen Klammern der Index des
gewünschten Feldelementes geschrieben wird.
Der Index beginnt mit 0 für das erste Element, es sind
ausschließlich positive Indizes im Bereich von 0 bis Größe-1
erlaubt.
Der sizeof-Operator kann benutzt werden, um die Größe eines Objektes zu ermitteln. Der Operator liefert die Byte-Anzahl im Datentyp size_t (siehe nächster Abschnitt).
Der Operator kann auf Datentypen oder auf Variablen angewandt werden. Wird er auf ein Feld angewandt, liefert er die Größe des gesamten Feldes in Byte.
Der Datentyp size_t ist ein vorzeichenloser ganzzahliger Datentyp, er wird benutzt, um Größen von Objekten zu speichern. Er wird hauptsächlich für Größen von Objekten im Speicher benutzt, Feldgrößen und Feldindizes.
Der C-Standard definiert keine feste Bitbreite für diesen
Datentyp, er muss aber groß genug sein, den gesamten logischen
Speicher durchmustern zu können.
Ob size_t einem unsigned, unsigned long, unsigned long long oder
einem anderen Datentyp entspricht, ist
implementierungsabhängig.
Soll ein size_t-Wert mit einer Funktion der
printf()-Familie ausgegeben werden, muss zunächst eine
Konvertierung in einen Datentyp erfolgen, für den ein Platzhalter
verfügbar ist.
Der Datentyp, in den konvertiert wird, muss groß genug gewählt
werden, so dass keine führenden signifikanten Bits abgeschnitten
werden.
#include <stdio.h> int main(void) { int a[5]; printf( "Groesse von int: %u Bytes.\n", (unsigned)sizeof(int) ); printf( "Groesse von a: %u Bytes.\n", (unsigned)sizeof(a) ); return 0; }
Felder können auch mehrdimensional sein. Bei der Definition muss die Feldgröße für jede Dimension angegeben werden.
Datentyp Variablenname[Anzahl1][Anzahl2];
int tf[2][3];
Die Deklaration bedeutet, dass tf ein zweidimensionales Feld von int-Werten ist. In der ersten Dimension hat das Feld die Größe 2. Jedes Element der ersten Dimension ist wiederum ein Feld mit 3 Elementen.
int tf[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } };
oder
int tf[2][3] = { /* Erste Dim: 0...1, zweite Dim: 0...2 */ { 1, 2, 3 }, /* tf[0][0], tf[0][1], tf[0][2] */ { 4, 5, 6 } /* tf[1][0], tf[1][1], tf[1][2] */ };
In der Initialisierung werden geschweifte Klammern verwendet.
Diese markieren die Grenzen der Elemente der ersten Dimension.
Bei weiteren Dimensionen wäre weitere Verschachtelung mit
geschweiften Klammern zu verwenden.
Prinzipiell wäre auch
int tf[2][3] = { 1, 2, 3, 4, 5, 6 };
möglich, hiervon wird allerdings abgeraten.
Insgesamt werden mehrdimensionale Felder eher selten verwendet.
Ein Zeiger speichert eine
Hauptspeicher-Adresse, an der sich ein Objekt befindet. Der
C-Compiler verknüpft damit noch die Information zum Datentyp des
Objektes.
Ein Zeiger wird mit
Typ *Name;
definiert.
Bevor ein Zeiger verwendet werden kann, muss er initialisiert, d.h. auf die Adresse des gewünschten Objektes gesetzt werden!
Es wird empfohlen, Zeiger bei der Deklaration zu initialisieren. Dabei werden Sie auf den speziellen Wert NULL gesetzt. Dieser Wert zeigt an, dass der Zeiger noch nicht auf die Adresse eines bestimmten Objektes gesetzt wurde.
Typ *Name = NULL;
Um Zeiger zu setzen, kann mit dem Adressoperator & die Adresse eines Objektes ermittelt werden, z.B.:
int i = 5;
int *ptr = NULL;
/* Zeiger setzen, so dass er auf i zeigt,
d.h. die Adresse von i wird in ptr gespeichert.
*/
ptr = &i;
Um einen Zeiger auf das erste Element eines Feldes zu setzen,
wird der Adressoperator nicht benötigt, es wird einfach nur der
Names des Feldes angegeben.
Damit kann
int notenliste[] = { 1, 5, 3, 2, 1, 2, 2, 3 }; int *ptr; ptr = &(notenliste[0]);
verkürzt werden zu:
int notenliste[] = { 1, 5, 3, 2, 1, 2, 2, 3 }; int *ptr; ptr = notenliste;
Mit
*Zeiger
wird auf das Element zugegriffen, auf das der Zeiger zeigt, d.h.
dessen Adresse im Zeiger gespeichert ist.
Damit kann sowohl der Wert geholt als auch gesetzt werden.
#include <stdio.h>
int i = 25; /* 0x1A */
int
main(void)
{
int *ptr;
/* Zeiger setzen, so dass er auf i zeigt,
d.h. die Adresse von i wird in ptr gespeichert.
*/
ptr = &i;
/* Variable setzen, auf die ptr zeigt.
*/
*ptr = 26;
/* Wert der Variable ausgeben, auf die ptr zeigt.
*/
printf("Wert: %d\n", *ptr);
return 0;
}
Mit den Operatoren ++ bzw -- kann ein Zeiger inkrementiert
(erhöht, auf das nächste Element weitergesetzt) bzw. dekrementiert
(verringert, auf das vorhergehende Element gesetzt) werden.
Voraussetzung dafür ist natürlich, dass der Zeiger auf ein Element
eines Feldes zeigt.
#include <stdio.h>
/** Die Noten von mehreren Studierenden.
*/
static int notenliste[] = { 1, 5, 3, 2, 1, 2, 2, 3 };
/** Anzahl der Elemente im Feld notenliste.
*/
static const size_t sz_notenliste = sizeof(notenliste)/sizeof(int);
int
main(void)
{
int *ptr = NULL; /* Zeiger */
size_t ind = 0; /* Index des aktuellen Elementes */
/* Zeiger ptr auf Adresse von notenliste[0] setzen.
*/
ptr = notenliste;
/* Notenliste durchmustern, Daten ausgeben.
*/
for (ind = 0; ind < sz_notenliste; ind++) {
printf(Student %u hat Note %d\n", (unsigned)(1 + ind), *(ptr++));
}
return 0;
}
Mit einer Indexoperation zeiger[Index] kann ebenfalls auf Feldelemente zugegriffen werden. Dabei greift zeiger[0] auf das Feldelement zu, dessen Adresse gerade im Zeiger gespeichert ist, zeiger[1] auf das folgende...
#include <stdio.h>
/** Die Noten von mehreren Studierenden.
*/
static int notenliste[] = { 1, 5, 3, 2, 1, 2, 2, 3 };
/** Anzahl der Elemente im Feld notenliste.
*/
static const size_t sz_notenliste = sizeof(notenliste)/sizeof(int);
int
main(void)
{
int *ptr = NULL; /* Zeiger */
size_t ind = 0; /* Index des aktuellen Elementes */
/* Zeiger ptr auf Adresse von notenliste[0] setzen.
*/
ptr = notenliste;
/* Notenliste durchmustern, Daten ausgeben.
*/
for (ind = 0; ind < sz_notenliste; ind++) {
printf(Student %u hat Note %d\n", (unsigned)(1 + ind), ptr[ind]);
}
return 0;
}
Das Konstrukt
Zeiger+Index
liefert die Adresse des Index-ten Elementes nach dem Element, dessen Adresse im Zeiger gespeichert ist.
Beispiel:
#include <stdio.h>
/** Die Noten von mehreren Studierenden.
*/
static int notenliste[] = { 1, 5, 3, 2, 1, 2, 2, 3 };
/** Anzahl der Elemente im Feld notenliste.
*/
static const size_t sz_notenliste = sizeof(notenliste)/sizeof(int);
int
main(void)
{
int *ptr = NULL; /* Zeiger */
/* Zeiger ptr auf Adresse von notenliste[0] setzen.
*/
ptr = notenliste;
/* Note des dritten Studenten ausgeben.
*/
printf(Student 3 hat Note %d\n", *(ptr + 2));
return 0;
}
Quelle: CERT C Coding Standard 〈1〉
Quelle: GNU Coding Standards 〈2〉
Typ Name[] = { Wert,...};ein Feld über Initialisierungswerte angelegt, können Sie die Anzahl der Feldelemente mit dem sizeof-Operator ermitteln
sizeof(Name)/sizeof(Typ)indem Sie die Größe des gesamten Feldes durch die Größe eines Feldelementes teilen (siehe Beispiel ex009.c unten).
/* Testprogramm zur Demonstration von Feldern */
/* Copyright (C) 2014-2017 - HS Schmalkalden. All rights reserved. */
#include <stdio.h>
/** Die Klausurnoten mehrerer Studenten einer Seminargruppe.
*/
int notenliste[] = {
1, 5, 3, 2, 1, 2, 2, 3
};
/** Anzahl Elemente im Feld notenliste.
*/
size_t sz_notenliste = sizeof(notenliste)/sizeof(int);
/** Hauptprogramm.
@return 0 bei Erfolg, alle anderen Werte bedeuten Fehler.
*/
int
main(void)
{
size_t i;
for (i = 0; i < sz_notenliste; i++) {
printf("Student %u hatte Note %d.\n", (unsigned)(i+1), notenliste[i]);
}
return 0;
}
/* vim: set ai sw=4 ts=4 expandtab : */
/* Testprogramm zur Demonstration von Zeigern */
/* Copyright (C) 2014-2017 - HS Schmalkalden. All rights reserved. */
#include <stdio.h>
/** Die Klausurnoten mehrerer Studenten einer Seminargruppe.
*/
int notenliste[] = {
1, 5, 3, 2, 1, 2, 2, 3
};
/** Anzahl Elemente im Feld notenliste.
*/
size_t sz_notenliste = sizeof(notenliste)/sizeof(int);
/** Hauptprogramm.
@return 0 bei Erfolg, alle anderen Werte bedeuten Fehler.
*/
int
main(void)
{
int *notenzeiger = NULL;
size_t i;
/* Auf Anfang des Feldes setzen */
notenzeiger = notenliste;
/* Fuer alle Elemente */
for (i = 0; i < sz_notenliste; i++) {
/* Note ausgeben */
printf("Student %u hatte Note %d.\n", (unsigned)(i+1), *notenzeiger);
/* Zeiger inkrementieren (weiterruecken) */
notenzeiger++;
}
return 0;
}
/* vim: set ai sw=4 ts=4 expandtab : */
1 | http://www.securecoding.cert.org |
2 | http://www.gnu.org/prep/standards/standards.html |