App下載

你知道C語言外部鏈接的靜態(tài)變量有哪幾種嗎?

猿友 2020-07-30 14:24:49 瀏覽數(shù) (3305)
反饋

上文說到了C語言自動變量的幾種類型,這里就說一下c語言外部鏈接的靜態(tài)變量的類型。

外部鏈接的靜態(tài)變量具有文件作用域、外部鏈接和靜態(tài)存儲期。該類別有時稱為外部存儲類別(external storage class),屬于該類別的變量稱為外部變量(external variable)。把變量的定義性聲明(defining declaration)放在所有函數(shù)的外面便創(chuàng)建了外部變量。

當然,為了指出該函數(shù)使用了外部變量,可以在函數(shù)中用關(guān)鍵字extern再次聲明。如果一個源代碼文件使用的外部變量定義在另一個源代碼文件中,則必須用extern在該文件中聲明該變量。如下所示:

int Errupt;           /* externally defined variable    */
double Up[100];       /* externally defined array       */
extern char Coal;     /* mandatory declaration if       */
                      /* Coal defined in another file   */
void next(void);
int main(void)
{
  extern int Errupt;  /* optional declaration           */


  extern double Up[]; /* optional declaration           */
  ...
}
void next(void)
{
  ...
}

注意,在main()中聲明Up數(shù)組時(這是可選的聲明)不用指明數(shù)組大小,因為第1次聲明已經(jīng)提供了數(shù)組大小信息。main()中的兩條extern聲明完全可以省略,因為外部變量具有文件作用域,所以ErruptUp從聲明處到文件結(jié)尾都可見。它們出現(xiàn)在那里,僅為了說明main()函數(shù)要使用這兩個變量。如果省略掉函數(shù)中的extern關(guān)鍵字,相當于創(chuàng)建了一個自動變量。去掉下面聲明中的extern

extern int Errupt;

便成為:

int Errupt;

這使得編譯器在main()中創(chuàng)建了一個名為Errupt的自動變量。它是一個獨立的局部變量,與原來的外部變量Errupt不同。該局部變量僅main()中可見,但是外部變量Errupt對于該文件的其他函數(shù)(如next())也可見。簡而言之,在執(zhí)行塊中的語句時,塊作用域中的變量將“隱藏”文件作用域中的同名變量。如果不得已要使用與外部變量同名的局部變量,可以在局部變量的聲明中使用auto存儲類別說明符明確表達這種意圖。外部變量具有靜態(tài)存儲期。因此,無論程序執(zhí)行到main()、next()還是其他函數(shù),數(shù)組Up及其值都一直存在。下面3個示例演示了外部和自動變量的一些使用情況。示例1中有一個外部變量Hocus。該變量對main()magic()均可見。

/* Example 1 */
int Hocus;
int magic();
int main(void)
{
   extern int Hocus;  // Hocus declared external
   ...
}
int magic()
{
   extern int Hocus;  // same Hocus as above
   ...
}

示例2中有一個外部變量Hocus,對兩個函數(shù)均可見。這次,在默認情況下對magic()可見。

/* Example 2 */
int Hocus;
int magic();
int main(void)
{
   extern int Hocus;  // Hocus declared external
   ...
}
int magic()
{
                      // Hocus not declared but is known
   ...
}

在示例3中,創(chuàng)建了4個獨立的變量。main()中的Hocus變量默認是自動變量,屬于main()私有。magic()中的Hocus變量被顯式聲明為自動,只有magic()可用。外部變量Hocusmain()magic()均不可見,但是對該文件中未創(chuàng)建局部Hocus變量的其他函數(shù)可見。最后,Pocus是外部變量,magic()可見,但是main()不可見,因為Pocus被聲明在main()后面。

/* Example 3 */
int Hocus;
int magic();
int main(void)
{
  int Hocus;        // Hocus declared, is auto by default
   ...
}
int Pocus;
int magic()
{
   auto int Hocus;  // local Hocus declared automatic
   ...
}

這3個示例演示了外部變量的作用域是:從聲明處到文件結(jié)尾。除此之外,還說明了外部變量的生命期。外部變量HocusPocus在程序運行中一直存在,因為它們不受限于任何函數(shù),不會在某個函數(shù)返回后就消失。

初始化外部變量

外部變量和自動變量類似,也可以被顯式初始化。與自動變量不同的是,如果未初始化外部變量,它們會被自動初始化為0。這一原則也適用于外部定義的數(shù)組元素。與自動變量的情況不同,只能使用常量表達式初始化文件作用域變量:

int x = 10;              // ok, 10 is constant
int y = 3 + 20;          // ok, a constant expression
size_t z = sizeof(int);  // ok, a constant expression
int x2 = 2 * x;          // not ok, x is a variable

(只要不是變長數(shù)組,sizeof表達式可被視為常量表達式。)

使用外部變量

下面來看一個使用外部變量的示例。假設(shè)有兩個函數(shù)main()critic(),它們都要訪問變量units??梢园?code>units聲明在這兩個函數(shù)的上面,如程序清單12.4所示(注意:該例的目的是演示外部變量的工作原理,并非它的典型用法)。

/* global.c  -- uses an external variable */
#include <stdio.h>
int units = 0;         /* an external variable      */
void critic(void);
int main(void)
{
    extern int units;  /* an optional redeclaration */


    printf("How many pounds to a firkin of butter?n");
    scanf("%d", &units);
    while ( units != 56)
        critic();
    printf("You must have looked it up!n");


    return 0;
}


void critic(void)
{
    /* optional redeclaration omitted */
    printf("No luck, my friend. Try again.n");
    scanf("%d", &units);
}

下面是該程序的輸出示例:

How many pounds to a firkin of butter?
14
No luck, my friend. Try again.
56
You must have looked it up!
(We did.)

注意,critic()是如何讀取units的第2個值的。當while循環(huán)結(jié)束時,main()也知道units的新值。所以main()函數(shù)和critic()都可以通過標識符units訪問相同的變量。用C的術(shù)語來描述是,units具有文件作用域、外部鏈接和靜態(tài)存儲期。

units定義在所有函數(shù)定義外面(即外部),units便是一個外部變量,對units定義下面的所有函數(shù)均可見。因此,critics()可以直接使用units變量。

類似地,main()也可直接訪問units。但是,main()中確實有如下聲明:

extern int units;

本例中,以上聲明主要是為了指出該函數(shù)要使用這個外部變量。存儲類別說明符extern告訴編譯器,該函數(shù)中任何使用units的地方都引用同一個定義在函數(shù)外部的變量。再次強調(diào),main()critic()使用的都是外部定義的units。

外部名稱

C99C11標準都要求編譯器識別局部標識符的前63個字符和外部標識符的前31個字符。這修訂了以前的標準,即編譯器識別局部標識符前31個字符和外部標識符前6個字符。你所用的編譯器可能還執(zhí)行以前的規(guī)則。外部變量名比局部變量名的規(guī)則嚴格,是因為外部變量名還要遵循局部環(huán)境規(guī)則,所受的限制更多。

定義和聲明

下面進一步介紹定義變量和聲明變量的區(qū)別??紤]下面的例子:

int tern = 1;            /* tern defined                 */
main()
{
     external int tern;  /* use a tern defined elsewhere */

這里,tern被聲明了兩次。第1次聲明為變量預留了存儲空間,該聲明構(gòu)成了變量的定義。第2次聲明只告訴編譯器使用之前已創(chuàng)建的tern變量,所以這不是定義。第1次聲明被稱為定義式聲明(defining declaration),第2次聲明被稱為引用式聲明(referencing declaration)。關(guān)鍵字extern表明該聲明不是定義,因為它指示編譯器去別處查詢其定義。

假設(shè)這樣寫:

extern int tern;
int main(void)
{

編譯器會假設(shè)tern實際的定義在該程序的別處,也許在別的文件中。該聲明并不會引起分配存儲空間。因此,不要用關(guān)鍵字extern創(chuàng)建外部定義,只用它來引用現(xiàn)有的外部定義。

外部變量只能初始化一次,且必須在定義該變量時進行。假設(shè)有下面的代碼:

// file one.c
char permis = 'N';
...
// file two.c
extern char permis = 'Y';   /* error */

file_two中的聲明是錯誤的,因為file_one.c中的定義式聲明已經(jīng)創(chuàng)建并初始化了permis。

以上就是關(guān)于C語言外部鏈接的靜態(tài)變量類型的說明,對C語言有興趣的同學可以看一下教程

C教程:http://m.hgci.cn/c/

C

0 人點贊