10.3. Lebensdauer von Variablen
Ob eine Variable in einem bestimmten Programmabschnitt verfügbar ist, hängt von deren Gültigkeitsbereich ab. Ob der Wert von Variablen nach dem Verlassen ihres Gültigkeitsbereichs erhalten oder zerstört wird, ist eine Frage ihrer Speicherklasse. Unter dem Gesichtspunkt der Speicherklasse kennt C zwei verschiedene Datenobjekte: statische und automatische.
Lokale Variablen sind per Voreinstellung automatische Datenobjekte. Solche Variablen werden beim Eintritt in eine Funktion automatisch erstellt und bei ihrem Verlassen ebenso automatisch wieder zerstört. Diese Eigenschaft können Sie lokalen Variablen auch explizit mit Hilfe des Schlüsselworts auto zuweisen. Allgemein wird aber darauf verzichtet, da es den Normalfall nur bestätigt, also redundant ist.
Beim Umgang mit automatischen Variablen müssen Sie stets daran denken, daß der Speicherbereich, der von einer automatischen Variablen benutzt wurde, nach dem Verlassen der Funktion für andere Zwecke freigegeben wird. Beim nächsten Aufruf der Funktion sind dann zwar wieder die gleichen Variablen verfügbar, aber alle Werte, die ihnen beim letzten Aufruf zugewiesen wurden, sind verloren. Hinzu kommt, daß automatische Variablen im Gegensatz zu statischen nicht initialisiert werden und daher beim Wiedereintritt in eine Funktion Zufallswerte enthalten.
#include <stdio.h>
void func1(void);
int main(void){
puts("1. Aufruf von func1():");
func1();
/* Auch beim 2. Aufruf von func1() enthält
* dort die Variable iTemp einen beliebigen
* Anfangswert. Der beim ersten Aufruf
* zugewiesene Wert von 5 * 2 ging nach
* Beendigung von func1() verloren.
*/
puts("\n2. Aufruf von func1():");
func1();
return 0;
}
void func1( void ){
int iTemp;
printf("Wert von iTemp vor Zuweisung: %d\n",
iTemp);
iTemp = 5 * 2;
printf("Wert von iTemp nach Zuweisung: %d\n",
iTemp);
}
Im Gegensatz zu lokalen sind globale Variablen immer statische Datenobjekte. Das bedeutet, daß für globale Variablen während der ganzen Programmausführung Speicherplatz reserviert bleibt und ihre Werte sich nur durch explizite Programmanweisungen verändern können. Es ist leicht einzusehen, daß Beständigkeit für eine globale Variable zwingend notwendig ist, da sie ja allen Funktionen jederzeit zur Verfügung stehen soll und der Programmierer sich darauf verlassen muß, daß sich ihr Wert nicht unbemerkt verändert. Neben den möglichen unerwünschten Nebeneffekten ("Spaghetti-Code") zeichnet sich damit für die exzessive Verwendung von globalen Variablen noch ein weiterer Nachteil ab: Ihr Umgang mit Speicher ist weniger wirtschaftlich als der von automatischen Variablen.
Um den Bedarf an globalen Variablen einzuschränken, bietet C die Möglichkeit, lokale Variablen als statische Objekte zu definieren. Als solche behalten sie erwartungsgemäß ihren Wert, auch wenn ihr Gültigkeitsbereich verlassen wird. Um eine lokale Variable als statische zu definieren, müssen sie das Schlüsselwort static verwenden. Es nimmt bei lokalen Variablen ausschließlich Einfluß auf die Speicherklasse, während es ja bei globalen Variablen deren Gültigkeitsbereich beschränkt.
Statische lokale Variablen haben mit den globalen Variablen gemeinsam, daß ihr Speicherplatz während der ganzen Laufzeit des Programms nicht freigegeben wird. Im Gegensatz zu letzteren erstreckt sich ihr Gültigkeitsbereich aber nur auf die Funktion, in der sie definiert wurden. Wenn der Programmierer statische Variablen nicht ausdrücklich initialisiert, dann erhalten sie genauso wie globale Variablen bei der Definition den Anfangswert 0.
/* static.c */
#include <stdio.h>
void func1(void);
int main(void){
int iCount = 0;
while( iCount++ <= 3)
/* func1() wird 4x aufgerufen */
func1();
return 0;
}
void func1( void ){
/* iTemp wird nur beim 1. Aufruf von func1()
* mit dem Wert 1 initialisiert! Bei allen
* folgenden Aufrufen wird hier keine
* Zuweisung vorgenommen!
*/
static int iTemp = 1;
printf("Wert von iTemp beim %d. Aufruf: %d\n",
iTemp, iTemp);
iTemp++;
}
Die Ausgabe von static belegt, daß bei jedem Aufruf von func1() der zuletzt gültige Wert von iTemp inkrementiert wird und daß die Initialisierung mit dem Wert 1 nur beim ersten Aufruf erfolgt:
Wert von iTemp beim 1. Aufruf: 1
Wert von iTemp beim 2. Aufruf: 2
Wert von iTemp beim 3. Aufruf: 3
Wert von iTemp beim 4. Aufruf: 4