Modularität, Gültigkeitsbereiche und Speicherklassen

C ist eine Programmiersprache, die modulares Arbeiten unterstützt. Als Modul soll im folgenden der Quelltext einer einzelnen Datei, eines einzelnen Sourcefiles, angesehen werden. Das Programm seinerseits kann aus 1 bis endlich vielen Modulen bestehen, jedes Modul aus 0 bis endlich vielen[20] Funktionen.

Beispiel: Ist der gesamte Quelltext eines Programms verteilt auf die Dateien main.c, sub1.c und sub2.c, so besitzt dieses Programm drei Module. Unter UNIX können diese nun mit dem Compileraufruf

cc main.c sub1.c sub2.c -o myprog

compiliert und zu einem ausführbaren Programmfile namens myprog zusammengebunden werden.

Modularität und Gültigkeitsbereiche

C kennt zwar keine Verschachtelung von Funktionen (wie Pascal); da aber in jedem Block (nicht nur in dem äußersten) Variablen deklariert werden können, ist hier zumindest in dieser Hinsicht eine entsprechende Blockstruktur wie bei Pascal zu finden. Wird in einem inneren Block eine Variable i deklariert, so überdeckt diese für die Dauer dieses Blockes eine eventuell in einem äußeren Block oder auf Grundebene (außerhalb aller Blöcke) deklarierte Variable (oder Konstante oder Funktion) i.

Ein C-Programm besteht aus einer Reihe von externen (globalen) Objekten, das können Variablen oder Funktionen sein. (main() ist auf jeden Fall ein solches externes Objekt.) Dabei wird extern als Kontrast zu intern verwendet und bezeichnet alle Objekte, die außerhalb einer Funktion vereinbart werden. Die Variablendeklarationen innerhalb einer Funktion führen dementsprechend zu internen Variablen. Auch die Variablen(namen) in den Parameterlisten sind in diesem Sinne interne Größen. Funktionen sind stets extern.

Per Default haben externe Objekte die Eigenschaft, daß alle Verweise auf sie mit gleichem Namen auch das gleiche Objekt bezeichnen, sogar aus Funktionen heraus, die separat compiliert worden sind. Dies nennt man externe Bindung[21].

Gültig ist eine interne Variable stets nur in der Einheit, in der sie deklariert wurde; eine externe Variable ist im gesamten Programm gültig mit der Einschränkung des Überdecktwerdens durch gleichnamige lokale Variablen.

Funktionen, die in C immer auf der globalen Ebene stehen müssen, sind von sich aus extern, d.h. aus jedem Modul kann auf sie zugegriffen werden, Prototyping vorausgesetzt. Dies kann durch explizites Hinzufügen des Schlüsselwortes extern vor den Rückgabetyp betont werden.

Beispiel:

extern float power(float,int);

Dagegen kann die Gültigkeit und Aufrufbarkeit einer Funktion auf das betreffende Modul beschränkt werden, indem vor den Rückgabetyp das Schlüsselwort static gesetzt wird.

Beispiel:

static float power(float,int);

Nun ist power() nur noch von Funktionen desselben Moduls aufrufbar!

Speicherklassen (auto, static, register, extern)

Es gibt grundsätzlich zwei Speicherklassen in C: automatisch (auto) und statisch (static). Zusammen mit dem Kontext der Deklaration eines Objektes (z.B. einer Variablen) bestimmen verschiedene Schlüsselwörter die zu verwendende Speicherklasse.

Automatische Objekte existieren (nur) lokal in einem Block und werden bei Verlassen des Blockes zerstört. Deklarationen innerhalb eines Blockes kreieren automatische Objekte, wenn keine Speicherklasse explizit angegeben wird. Mit dem Schlüsselwort register deklarierte Objekte sind automatisch, werden jedoch nach Möglichkeit in Hardware-Registern verwaltet.

Statische Objekte können lokal in einem Block, in einer Funktion oder auch außerhalb von allen Blöcken deklariert werden; sie behalten ihre Speicherplätze und Werte aber in jedem Fall bei Verlassen von und beim Wiedereintritt in Blöcke und Funktionen bei! In einem Block (und in einer Funktion) werden Objekte mit dem Schlüsselwort static als statisch deklariert. Außerhalb von allen Blöcken sind Objekte stets statisch. Mit static können sie lokal für ein Modul (Quelltextfile) vereinbart werden, dadurch erhalten sie eine sogenannte interne Bindung (internal linkage); für ein gesamtes Programm werden sie global bekannt, wenn keine Speicherklasse angegeben wird oder aber durch Verwendung des Schlüsselwortes extern, dadurch erhalten sie externe Bindung (external linkage).

Übersicht: Speicherklassen, Gültigkeitsbereiche und Lebensdauer

           Klasse             Gültigkeit          Lebensdauer    Automatische   
                                                                 Initialisieru  
                                                                 ng?            
auto                          Block               Block          nein           
register                      Block               Block          nein           
extern                        Programm            Programmlauf   ja             
static (blockintern)          Block               Programmlauf   ja             
static (außerhalb aller       Quelldatei (Modul)  Programmlauf   ja             
Blöcke)                                                                         

Attribute für Datentypen: const und volatile

ANSI C kennt zwei Attribute für Datentypen: const und volatile. Diese Attribute können mit jeder Typangabe gekoppelt auftreten.

Das Schlüsselwort const

Ein Objekt mit dem Attribut const (für konstant) muß initialisiert werden und kann anschließend nicht mehr verändert werden, darf also insbesondere nicht neue Werte zugewiesen bekommen. Der Compiler hat die Möglichkeit, const-Objekte in anderen Speicherbereichen zu verwalten als normale Variablen.

Beispiel:

const double PI=3.1415926;

Das Schlüsselwort volatile

Mit dem Attribut volatile wird dem Compiler mitgeteilt, daß das entsprechende Objekt durch externe Einflüsse geändert werden kann, z.B. durch die Systemuhr. Der Compiler benötigt eine solche Angabe, damit er nicht anhand des Programmcodes davon ausgeht, daß sich ein Objekt nicht ändert und eventuell durch eine ansonsten sinnvolle Optimierung das Programm verfälscht.