Udostępnij za pośrednictwem


Specyfikatory klasy magazynowania dla deklaracji na poziomie zewnętrznym (C)

Zmienne zewnętrzne są zmiennymi w zakresie pliku. Są zdefiniowane poza jakąkolwiek funkcją i są potencjalnie dostępne dla wielu funkcji. Funkcje mogą być definiowane tylko na poziomie zewnętrznym i dlatego nie mogą być zagnieżdżane. Domyślnie wszystkie odwołania do zmiennych zewnętrznych i funkcji tej samej nazwy są odwołaniami do tego samego obiektu, co oznacza, że mają zewnętrzne powiązania. (Możesz użyć słowa kluczowego static , aby zastąpić to zachowanie).

Deklaracje zmiennych na poziomie zewnętrznym to definicje zmiennych (deklaracje definiujące) lub odwołania do zmiennych zdefiniowanych gdzie indziej (odwołujących się do deklaracji).

Zewnętrzna deklaracja zmiennej, która również inicjuje zmienną (jawnie lub niejawnie) jest deklaracją definiującą zmienną. Definicja na poziomie zewnętrznym może przybierać różne formy:

  • Zmienna zadeklarowana za pomocą specyfikatora static klasy magazynu. Możesz jawnie zainicjować static zmienną za pomocą wyrażenia stałego, zgodnie z opisem w temacie Inicjowanie. Jeżeli pominięto inicjator, zmienna jest inicjowana domyślnie na wartość 0. Na przykład, następujące dwie instrukcje są rozważane jako definicje zmiennej k.

    static int k = 16;
    static int k;
    
  • Zmienna jawnie zainicjowana na poziomie zewnętrznym. Na przykład, int j = 3; jest definicją zmiennej j.

W deklaracjach zmiennych na poziomie zewnętrznym (czyli poza wszystkimi funkcjami), można użyć specyfikatora static klasy magazynu lub extern całkowicie pominąć specyfikator klasy magazynu. Nie można używać auto terminali i register storage-class-specifier na poziomie zewnętrznym.

Gdy zmienna jest zdefiniowana na poziomie zewnętrznym, jest widoczna w pozostałej części jednostki translacji. Zmienna nie jest widoczna przed jej deklaracją, w tym samym pliku źródłowym. Ponadto, nie jest widoczna w innych plikach źródłowych programu, chyba że deklaracja odwołaniowa sprawia, że staje się widoczna, jak opisano poniżej.

Zasady dotyczące static uwzględnienia:

  • Zmienne zadeklarowane poza wszystkimi blokami bez słowa kluczowego static zawsze zachowują swoje wartości w całym programie. Aby ograniczyć dostęp do określonej jednostki tłumaczenia, należy użyć słowa kluczowego static . Zapewnia to im wewnętrzne powiązania. Aby stworzyć je globalnie dla całego programu, należy pominąć jawną klasę magazynu lub użyć słowa kluczowego extern (patrz zasady na następnej liście). Zapewnia to im powiązania zewnętrzne. Wewnętrzne i zewnętrzne powiązania są również omówione w linkage.

  • Można zdefiniować zmienną na poziomie zewnętrznym tylko raz w programie. Możesz zdefiniować inną zmienną o tej samej nazwie i static specyfikatorze klasy magazynu w innej jednostce tłumaczenia. Ponieważ każda static definicja jest widoczna tylko w ramach własnej jednostki tłumaczenia, nie występuje konflikt. Zapewnia przydatny sposób ukrywania nazw identyfikatorów, które muszą być współużytkowane przez funkcje pojedynczej jednostki tłumaczenia, ale nie są widoczne dla innych jednostek tłumaczenia.

  • Specyfikator static klasy magazynu może również mieć zastosowanie do funkcji. Jeśli deklarujesz funkcję static, jej nazwa jest niewidoczna poza plikiem, w którym jest zadeklarowana.

Reguły korzystania z extern są:

  • Specyfikator klasy magazynu extern deklaruje odwołanie do zmiennej zdefiniowanej w innym miejscu. Możesz użyć extern deklaracji, aby utworzyć definicję w innym pliku źródłowym, lub ustawić zmienną widoczną przed jej definicją w tym samym pliku źródłowym. Po zadeklarowaniu odwołania do zmiennej na poziomie zewnętrznym zmienna jest widoczna w pozostałej części jednostki tłumaczenia, w której występuje zadeklarowane odwołanie.

  • Aby odwołanie extern było prawidłowe, zmienna do której się odnosi, musi być zdefiniowana raz i tylko raz, na poziomie zewnętrznym. Ta definicja (bez klasy magazynu extern) może być w dowolnej jednostce translacji, tworzącej program.

Przykład

Poniższy przykład ilustruje deklaracje zewnętrzne:

/******************************************************************
                      SOURCE FILE ONE
*******************************************************************/
#include <stdio.h>

extern int i;                // Reference to i, defined below
extern void other ( void );  // Reference to other(), defined in second source file
void next( void );           // Function prototype

int main()
{
    i++;
    printf_s( "%d\n", i );   // i equals 4
    next();
}

int i = 3;                  // Definition of i

void next( void )
{
    i++;
    printf_s( "%d\n", i );  // i equals 5
    other();
}

/******************************************************************
                      SOURCE FILE TWO
*******************************************************************/
#include <stdio.h>

extern int i;              // Reference to i in
                           // first source file
void other( void )
{
    i++;
    printf_s( "%d\n", i ); // i equals 6
}

Dwa pliki źródłowe w tym przykładzie zawierają łącznie trzy zewnętrzne deklaracje i. Tylko jedna deklaracja jest "deklaracją definiującą". Deklaracja ta,

int i = 3;

definiuje zmienną globalną i oraz inicjuje ją początkową wartością 3. Deklaracja i "odwołująca się" w górnej części pierwszego pliku źródłowego przy użyciu extern sprawia, że zmienna globalna jest widoczna przed jego deklaracją definiującą w pliku. Deklaracja odwołaniowa i w drugim pliku źródłowym również sprawia, że zmienna jest widoczna w tym pliku źródłowym. Jeśli wystąpienie definiujące zmiennej nie jest dostarczone w jednostce tłumaczenia, kompilator zakłada deklarację odwołaniową

extern int x;

deklaracja odwołaniowa i oraz odwołanie definiujące

int x = 0;

pojawia się w innej jednostce translacji programu.

Wszystkie trzy funkcje main, next i other, wykonują to samo zadanie: zwiększają i oraz drukują. Drukowane są wartości 4, 5 i 6.

Gdyby zmienna i nie została zainicjowana, zostałaby ustawiona wartość 0 automatycznie. W tym przypadku byłyby wypisane wartości 1, 2 i 3. Zobacz Inicjowanie , aby uzyskać informacje o inicjowaniu zmiennych.

Zobacz też

Klasy magazynu w języku C