static (Schlüsselwort)

aus Wikipedia, der freien Enzyklopädie
(Weitergeleitet von Static (Informatik))
Wechseln zu: Navigation, Suche

Das Schlüsselwort static ist ein Zusatz bei der Deklaration von Variablen oder Funktionen in Programmiersprachen wie C, C++, Java, C# oder VB.NET.

Verwendung[Bearbeiten]

Verwendung Programmiersprache
Speicherklasse (storage duration) C, C++, Java, VB.NET
Linkage C, C++
Deklaration von Klassen-Variablen und -Methoden C++, Java, VB.NET
Mindestgröße für Array-Parameter C99

static als Speicherklasse[Bearbeiten]

Die Speicherklasse (engl. storage class) static definiert die „Lebenszeit“ einer Variable. Die Lebenszeit beginnt mit dem Programmstart (bei globalen Variablen) oder mit dem ersten Durchlauf der Deklaration (bei lokalen Variablen) und endet mit dem Ende des Programms.

Beispiel in C oder C++[Bearbeiten]

int summiere(int s)
{
    static int summe = 100; // Variable wird beim ersten Durchlauf der Deklaration initialisiert.
    summe += s;
    return summe;
}

Globale Variablen besitzen stets die Speicherklasse "static" (engl. static storage duration). Das Schlüsselwort static ändert bei ihnen die Linkage, nicht die Speicherklasse!

Linkage[Bearbeiten]

Die Linkage eines Symbols (wie z.B. eines Variablen- oder Funktionsnamens) gibt an, wie mit dem Symbol beim Linken umgegangen wird.

Globale Variablen haben in C standardmäßig external linkage, das heißt, sie sind von anderen Übersetzungseinheiten aus sichtbar und existieren nur einmal im endgültigen Programm. Wird ein Symbol mit external linkage in mehreren Übersetzungseinheiten definiert (und nicht bloß deklariert!), gibt es beim Linken einen Linkerfehler ("double definition error").

Um Variablen und Funktionen jeweils pro Übersetzungseinheit zu definieren, muss man sie mit internal linkage deklarieren. Dies geschieht in C und C++ durch das Schlüsselwort static bei der Deklaration einer globalen Variable oder Funktion.

Beispiel in C[Bearbeiten]

Übersetzungseinheit foo.c
    int x;        // external linkage
    extern int y; // nur Deklaration!
    static int z; // internal linkage
    const int c = 42; // external linkage in C, internal in C++
    int f();      // nur Deklaration
    int g() { return 0; }
    static int h() { return 1; }
Übersetzungseinheit bar.c
    int x;        // external linkage
    int y;        // hier wird y auch definiert
    static int z; // internal linkage
    const int c = 23; // external linkage in C, internal in C++
    int f() { return 1; }
    int g() { return 0; }
    static int h() { return 2; }

Versucht man, diese beiden Dateien zu compilieren und anschließend zusammenzulinken, gibt es Linkerfehler für die Variable x und die Funktion g(), da diese jeweils zweimal definiert wurden.

Die Variable y und die Funktion f() wurden nur einmal definiert und existieren nur einmal im Programm.

Es gibt in jeder Übersetzungseinheit eine eigene Variable z und jeweils eine Funktion h(), die trotz ihres gleichen Namens nichts miteinander zu tun haben (internal linkage).

C und C++ verhalten sich unterschiedlich bei der Default-Linkage von const-Variablen. Während diese bei C weiterhin external linkage haben und somit obiges Beispiel auch für c einen Linkerfehler geben würde, haben sie bei C++ internal linkage und existieren somit pro Übersetzungseinheit, sofern sie nicht durch den Compiler als Konstante wegoptimiert werden können.

static bei Klassenmembern[Bearbeiten]

In C++ und Java werden Deklarationen von Membervariablen und -funktionen mit dem Schlüsselwort static versehen, um anzuzeigen, dass diese Variable oder Funktion ohne eine Instanz der Klasse existiert und benutzt werden kann.

Beispiel in C++[Bearbeiten]

class C
{
public:
    int i;
    static int s;  // nur Deklaration!
};
 
int C::s = 42; // Definition der statischen Membervariablen
 
int usage()
{
    C::s = 1; // Benutzung ohne ein Objekt vom Typ C
    C c;
    c.i = 17;
    c.s = 0;  // möglich, aber gefährlich. Compiler kann hier warnen.
}

Beispiel in VB.NET[Bearbeiten]

In VB.NET wird das Schlüsselwort Static nur innerhalb einer Methode[1] als Suffix für eine lokale Variable verwendet. Es kennzeichnet, dass die Variable nicht bei jedem Methodenaufruf neu initialisiert wird, sondern den Wert annimmt, den sie beim vorherigen Methodenaufruf zuletzt hatte (Lebensdauer = Programmlebensdauer). Dass ein Klassenmember unabhängig von einer Instanz verwendet werden kann wird - abweichend von anderen Sprachen - mit dem Schlüsselwort Shared[2] markiert. In den CLI-Sprachen können keine Member außerhalb einer Klasse stehen und einen Linker gibt es dort ebenfalls nicht, so dass die Bedeutung der geringeren Sichtbarkeit für den Linker ebenfalls entfällt. Damit hat in VB.Net das Static-Schlüsselwort eine eindeutige, kontextunabhängige Bedeutung.

Das folgende Beispiel zeigt eine banale Anwendung innerhalb von Threads; eine Static-Variable wird nur ein einziges Mal initialisiert, selbst dann, wenn die aktuelle Prozedur/die aktuelle Thread-Iteration bereits beendet wurde und der Logik nach ein anderer Thread nun reinitialisieren sollte:

Imports System.Threading
Public Class StaticDemo
   Private Shared ReadOnly mMutex As New Mutex                                       '1 Kopie für alle Threads => Shared
   Public Sub StartThreads()
      For i As UInteger = 1 To 10
         ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf IncrementThread))   '10 Threads starten
      Next
   End Sub
 
   Private Sub IncrementThread()
      Dim tId As Integer = Thread.CurrentThread.ManagedThreadId                      'hier kann jeder Zugriff verfolgt werden
      Static mNumber As UInteger = 0                                                 '1 Kopie für alle Threads, Kontextbeschränkt => Static
 
      While mMutex.WaitOne         
         mNumber += 1
         mMutex.ReleaseMutex()
      End While
 
    End Sub
End Class

C#, Java[Bearbeiten]

In den Programmiersprachen Java und C# ist das Schlüsselwort static ebenfalls kontextabhängig, die geringere Sichtbarkeit für den Linker entfällt jedoch bei diesen Sprachen, so dass noch analog zu C++ und VB.Net die Instanzunabhängigkeit auf Klassenebene und die Lebensdauer Programmlaufzeit auf Methodenebene bleiben.

Zur Initialisierung von instanzunabhängigen Membervariablen gibt es statische Konstruktoren, die keine Parameter annehmen können und vor dem ersten Aufruf eines statischen Members und vor dem Erstellen der ersten Klasseninstanz automatisch aufgerufen werden. Sie werden ebenfalls mit dem Schlüsselwort static gekennzeichnet, die genaue Syntax ist jedoch bei Java und C# verschieden:

Java
class Beispiel {
  static {
    //...
  }
}
C#
class Beispiel {
  static Beispiel() {
    //...
  }
}

static bei Array-Parametern[Bearbeiten]

Da Arrays in C als "Zeiger auf das erste Element" an Funktionen übergeben werden, ist der Funktion die Größe des Arrays nicht bekannt. In C99 wurde die Möglichkeit geschaffen, bei der Deklaration der Funktion eine Mindestgröße mitzugeben. Dies erlaubt zum einen eine bessere Typprüfung und – vor allem im Zusammenhang mit dem restrict-Schlüsselwort – die Erzeugung performanteren Codes.

Beispiel
void hash(unsigned char digest[static 64], const char* data, size_t size);
 
int main()
{
    unsigned char buffer[32];
    hash(buffer, data, length);  // Compilerwarnung: hash erwartet mind. 64 Bytes, buffer ist aber kleiner!
}

Einzelnachweise[Bearbeiten]

  1. Vorlage:Internetquelle/Wartung/Zugriffsdatum nicht im ISO-FormatStatic (Visual Basic). Microsoft, abgerufen am 28. Oktober 2012 (deutsch).
  2. Vorlage:Internetquelle/Wartung/Zugriffsdatum nicht im ISO-FormatShared (Visual Basic). Microsoft, abgerufen am 28. Oktober 2012 (deutsch).

Weblinks[Bearbeiten]