10.8 Arrays und Zeiger als Funktionsparameter
Dieses Thema wurde bereits in Abschnitt 9.1.8, »Arrays an Funktionen übergeben«, behandelt und soll hier noch einmal kurz aufgegriffen werden. Es kann ja sein, dass Sie unserem Vorschlag gefolgt sind und von Abschnitt 9.1.8 direkt zu Kapitel 10 gesprungen sind. Jetzt, da Sie mit Zeigern vertraut sind, können Sie sich Kapitel 9 noch einmal in Ruhe vornehmen.
Nun aber zurück zur Übergabe von Arrays an Funktionen. Da, wie gesagt, Arrays nicht als Ganzes direkt an Funktionen übergeben werden können, wird immer nur die Adresse des ersten Array-Elements übergeben. Daher sind die folgenden zwei Deklarationen der formalen Parameter einer Funktion völlig gleichbedeutend, weil der Compiler im Grunde eben nur an der Adresse des ersten Array-Elements interessiert ist:
void modArr(int arr[], size_t s);
// und
void modArr(int *arr, size_t s);
Sie können solche Funktionen auf mehrere Arten aufrufen. Allerdings wird immer die (Anfangs)adresse des Arrays an die Funktion übergeben, damit diese weiß, wo sich das Array im Speicher befindet. Auf diese Weise bekommt die aufrufende Funktion auch einen direkten Zugriff auf die Daten und kann diese daher direkt manipulieren (Stichwort: Call by Reference).
In der Regel wird außerdem bei der Übergabe eines Arrays an eine Funktion auch die Anzahl der Elemente als weiteres Argument mit übergeben, damit in der Funktion die korrekte Anzahl von Elementen im Array abgearbeitet werden kann. Dies wurde ja schon vorher angedeutet, wir wollen Ihnen jedoch noch einige Dinge mit auf den Weg geben, die Sie verwenden können, um die Übergabe von Arrays an Funktionen noch sicherer zu machen.
10.8.1 const-Array-Parameter
In diesem Zusammenhang finden Sie häufig Array-Parameter, die mit dem Qualifizierer const ausgezeichnet sind. Mit einem const-Array-Parameter verhindern Sie Modifikationen der Array-Werte der aufrufenden Funktion. Solche Array-Elemente sind dann in der Funktion konstant, und eine versehentliche Änderung der Daten wird verhindert. Ein Beispiel mit zwei gleichbedeutenden Funktionsprototypen wäre:
void printArr(const int arr[], size_t s);
// gleichwertig:
void printArr(const int *arr, size_t s);
Eine Änderung der Elemente im Array arr ist in diesem Beispiel nicht mehr möglich, weil es als const qualifiziert ist. Eine Zuweisung wie
arr[0] = 1234; // Fehler in printArr, da const
innerhalb der Funktion ist nicht mehr möglich und wird vom Compiler mit einer Fehlermeldung verweigert. In der Praxis ist es daher guter Stil, ein Array mit const zu qualifizieren, wenn die Funktion ohnehin keine Manipulation daran vornimmt. Dies ist dann auch mit ein Grund, warum die Funktion printf() auszugebende Zeichenketten als const char* definiert.
Es folgt nun ein komplettes Beispiel zur Übergabe von Arrays an Funktionen:
00 // Kapitel10/fnc_array.c
01 #include <stdio.h>
02 #include <stdlib.h>
03 void modArr(int *arr, size_t s) {
04 for(int i=0; i<s; ++i) {
05 arr[i]*=2;
06 }
07 }
08 void printArr(const int *arr, size_t s) {
09 for(int i=0; i<s; ++i) {
10 printf("%d \n", arr[i]);
11 }
12 printf("\n");
13 }
14 int main(void) {
15 int iarr[] = { 11, 22, 33, 44, 55 };
16 modArr(iarr, sizeof(iarr)/sizeof(int));
17 printArr(iarr, sizeof(iarr)/sizeof(int));
18 return EXIT_SUCCESS;
19 }
In den Zeilen (03) bis (07) finden Sie die Funktion modArr(), die nichts anderes tut, als den Inhalt der einzelnen Werte eines an die Funktion übergebenen Arrays zu verdoppeln. In Zeile (16) rufen Sie diese Funktion mit der Anfangsadresse des Arrays und der Anzahl der darin enthaltenen Elemente auf. Diese wurde hier ganz einfach mit sizeof(array)/sizeof(Datentyp) übergeben. Ein reines sizeof(array) würde nur die Größe des Arrays in Bytes zurückliefern, weshalb Sie diesen Wert noch durch die Größe des Datentyps teilen müssen, um die Anzahl der Elemente zu ermitteln. Hier müssen Sie in der Tat aufpassen, denn sizeof(array) gibt wirklich die Größe in Bytes zurück!
Die zweite Funktion printArr() in den Zeilen (08) bis (13) hat einen const-Array-Parameter, um so ein versehentliches Ändern der Array-Elemente in der Funktion zu verhindern. Die Funktion gibt die Werte der einzelnen Array-Elemente aus und wird in Zeile (17) mit der Anfangsadresse des Arrays und der Anzahl der Elemente aufgerufen.