App下載

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

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

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

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

當(dāng)然,為了指出該函數(shù)使用了外部變量,可以在函數(shù)中用關(guān)鍵字extern再次聲明。如果一個(gè)源代碼文件使用的外部變量定義在另一個(gè)源代碼文件中,則必須用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í)(這是可選的聲明)不用指明數(shù)組大小,因?yàn)榈?次聲明已經(jīng)提供了數(shù)組大小信息。main()中的兩條extern聲明完全可以省略,因?yàn)橥獠孔兞烤哂形募饔糜?,所?code>Errupt和Up從聲明處到文件結(jié)尾都可見。它們出現(xiàn)在那里,僅為了說明main()函數(shù)要使用這兩個(gè)變量。如果省略掉函數(shù)中的extern關(guān)鍵字,相當(dāng)于創(chuàng)建了一個(gè)自動(dòng)變量。去掉下面聲明中的extern

extern int Errupt;

便成為:

int Errupt;

這使得編譯器在main()中創(chuàng)建了一個(gè)名為Errupt的自動(dòng)變量。它是一個(gè)獨(dú)立的局部變量,與原來的外部變量Errupt不同。該局部變量?jī)Hmain()中可見,但是外部變量Errupt對(duì)于該文件的其他函數(shù)(如next())也可見。簡(jiǎn)而言之,在執(zhí)行塊中的語句時(shí),塊作用域中的變量將“隱藏”文件作用域中的同名變量。如果不得已要使用與外部變量同名的局部變量,可以在局部變量的聲明中使用auto存儲(chǔ)類別說明符明確表達(dá)這種意圖。外部變量具有靜態(tài)存儲(chǔ)期。因此,無論程序執(zhí)行到main()、next()還是其他函數(shù),數(shù)組Up及其值都一直存在。下面3個(gè)示例演示了外部和自動(dòng)變量的一些使用情況。示例1中有一個(gè)外部變量Hocus。該變量對(duì)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中有一個(gè)外部變量Hocus,對(duì)兩個(gè)函數(shù)均可見。這次,在默認(rèn)情況下對(duì)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個(gè)獨(dú)立的變量。main()中的Hocus變量默認(rèn)是自動(dòng)變量,屬于main()私有。magic()中的Hocus變量被顯式聲明為自動(dòng),只有magic()可用。外部變量Hocus對(duì)main()magic()均不可見,但是對(duì)該文件中未創(chuàng)建局部Hocus變量的其他函數(shù)可見。最后,Pocus是外部變量,magic()可見,但是main()不可見,因?yàn)?code>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個(gè)示例演示了外部變量的作用域是:從聲明處到文件結(jié)尾。除此之外,還說明了外部變量的生命期。外部變量HocusPocus在程序運(yùn)行中一直存在,因?yàn)樗鼈儾皇芟抻谌魏魏瘮?shù),不會(huì)在某個(gè)函數(shù)返回后就消失。

初始化外部變量

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

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

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

使用外部變量

下面來看一個(gè)使用外部變量的示例。假設(shè)有兩個(gè)函數(shù)main()critic(),它們都要訪問變量units??梢园?code>units聲明在這兩個(gè)函數(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個(gè)值的。當(dāng)while循環(huán)結(jié)束時(shí),main()也知道units的新值。所以main()函數(shù)和critic()都可以通過標(biāo)識(shí)符units訪問相同的變量。用C的術(shù)語來描述是,units具有文件作用域、外部鏈接和靜態(tài)存儲(chǔ)期。

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

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

extern int units;

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

外部名稱

C99C11標(biāo)準(zhǔn)都要求編譯器識(shí)別局部標(biāo)識(shí)符的前63個(gè)字符和外部標(biāo)識(shí)符的前31個(gè)字符。這修訂了以前的標(biāo)準(zhǔn),即編譯器識(shí)別局部標(biāo)識(shí)符前31個(gè)字符和外部標(biāo)識(shí)符前6個(gè)字符。你所用的編譯器可能還執(zhí)行以前的規(guī)則。外部變量名比局部變量名的規(guī)則嚴(yán)格,是因?yàn)橥獠孔兞棵€要遵循局部環(huán)境規(guī)則,所受的限制更多。

定義和聲明

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

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

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

假設(shè)這樣寫:

extern int tern;
int main(void)
{

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

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

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

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

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

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

C

0 人點(diǎn)贊