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 zmiennejk
.static int k = 16; static int k;
Zmienna jawnie zainicjowana na poziomie zewnętrznym. Na przykład,
int j = 3;
jest definicją zmiennejj
.
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 kluczowegostatic
. 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 kluczowegoextern
(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żdastatic
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 magazynuextern
) 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.