Seitenleiste

Scopes

Als Scope bezeichnet man den Bereich innerhalb zweier geschweifter Klammern. Man spricht auch von Anweisungsblöcken.

Abbau von Variablen am Ende von Scopes

Allerdings beschreiben Scopes nicht nur eine Reihe von Anweisungen, wie die Definition von Variablen, sondern auch implizit (also ohne dass der Programmierer es hinschreiben muss) werden am Ende eines Scopes auch alle definierten Variablen wieder entfernt. Daher lässt sich folgendes Programm nicht kompilieren.

#include <stdlib.h>
#include <stdio.h>
 
int global = 1234;
 
int main( void )
{
  int local = 4;
 
  if( local == 4 )
  { // Neuer Scope
 
    int i = 1;    
 
  } // Ende des Scopes, alle lokalen Variablen des Scopes werden abgebaut.
  else
  { // Neuer Scope
 
    int i = 0;    
 
  } // Ende des Scopes, alle lokalen Variablen des Scopes werden abgebaut.
 
  printf( "i hat den Wert: %d\n" i );
 
  return EXIT_SUCCESS;
}

In diesem Programm gibt es zwei voneinander unabhängige Variablen i, die jeweils am Ende ihres Scopes wieder abgebaut werden, also zum Zeitpunkt, an dem i mit printf ausgegeben werden soll, gar nicht mehr existieren. Um derartiges zu schreiben, muss sich die Variable i in einem Scope befinden, der noch nicht abgebaut wurde, wenn i ausgegeben wird:

#include <stdlib.h>
#include <stdio.h>
 
int global = 1234;
 
int main( void )
{
  int local = 4;
  int i;
 
  if( local == 4 )
  { // Neuer Scope
 
    i = 1;
 
  } // Ende des Scopes, alle lokalen Variablen des Scopes werden abgebaut.
  else
  { // Neuer Scope
 
    i = 0;
 
  } // Ende des Scopes, alle lokalen Variablen des Scopes werden abgebaut.
 
  printf( "i hat den Wert: %d\n" i );
 
  return EXIT_SUCCESS;
}

Verdecken von lokalen Variablen

Bei lokalen Variablen glauben viele, dass die Variable nur innerhalb der Funktion sichtbar wäre. Ausschlaggebend ist allerdings der Anweisungsblock, also der Bereich zwischen den geschweiften Klammern, dem sogenannten Scope. Man kann die Sichtbarkeit auch innerhalb einer Funktion eingrenzen:

#include <stdlib.h>
#include <stdio.h>
 
int global = 1234;
 
int main( void )
{
  int local = 4;
  int local2 = 10;
  printf( "main: Wert der lokalen Variable: %d/%d\; global: %dn", local, local2, global );
 
  { // Neuer Scope
    int local = 4711;         // neue Variable 'local', die die vorherige Variable überdeckt.
 
    printf( "main: Wert der lokalen Variable: %d/%d\; global: %dn", local, local2, global );
  } // Ende des Scopes, alle lokalen Variablen des Scopes werden abgebaut.
 
  { // Neuer Scope
    int global = 4321;         // neue Variable 'local', die die vorherige Variable überdeckt.
 
    printf( "main: Wert der lokalen Variable: %d/%d\; global: %dn", local, local2, global );
  } // Ende des Scopes, alle lokalen Variablen des Scopes werden abgebaut.
 
  printf( "main: Wert der lokalen Variable: %d/%d\; global: %dn", local, local2, global );
 
  return EXIT_SUCCESS;
} // hier geht local verloren

Das Ergebnis ist nun recht interessant:

main: Wert der lokalen Variable: 4/10; global: 1234
main: Wert der lokalen Variable: 4711/10; global: 1234
main: Wert der lokalen Variable: 4/10; global: 4321
main: Wert der lokalen Variable: 4/10; global: 1234

Schauen wir uns zunächst local und local2 an: Für das erste printf() findet der Compiler im aktuellen Scope die Variable local, wie auch die Variable local2 und gibt sie aus. In der zweiten Ausgabe-Zeile findet der Compiler im aktuellen Scope local, nicht aber local2. Auf der Suche nach local2 wechselt er also in einen höher gelegenen Scope, wo local2 auch definiert wurde. Die lokale Variable lokal im Scope verdeckt also die Variable lokal im übergeordneten Scope. Zwischen der zweiten und der dritten Ausgabezeile, wird ein Scope vernichtet, also auch die Variable lokal im Scope, sowie ein neuer Scope angelegt, inklusive einer neuen Variable global. Wieder muss der Compiler printf() mit passenden Variablen bestücken und während er local und local2 aus dem höher gelegenen Scope nehmen muss, findet er global bereits im aktuellen Scope. Die lokale Variable global verdeckt also die globale Variable global. Für die letzte Zeile finden sich die beiden lokalen Variablen local und local2 im aktuellen Scope und global findet sich wieder global. Hier sieht man auch nochmal deutlich, dass in den Scopes neue Variablen verwendet wurde, denn die alten Variablen haben ihre Werte behalten.

Wenn ihr nun verstanden habt, dass der Compiler einen Bezeichner zunächst im lokalen Scope sucht und sich dann Scope für Scope hocharbeitet, so erkennt ihr, dass die globalen Variablen einfach nur im höchsten Scope liegen, also eigentlich gar keine Besonderheit darstellen. Für den höchsten Scope spart man sich lediglich die geschweiften Klammern vor und nach dem Programm.