天天看點

static和extern的關系

static:

  1. 在c語言中,static可以修飾全局變量,局部變量和函數。

    在c++中static修飾類的成員函數,那麼這個函數屬于這個類,而不是屬于這個類的特定對象,static成員函數沒有this指針。static修飾類中的變量,表示該變量是該類所有對象共享的,而且這個變量在儲存空間中隻有一個副本,靜态成員函數隻能通路靜态成員函數和靜态成員變量,不能通路非靜态的。

    2.1. 修飾局部變量

    一般的局部變量是在棧中存放的,随着函數的生命周期結束而結束。

    但是如果用static進行修飾的話,該變量便存放在靜态資料區,其生命周期一直持續到整個程式執行結束。但是在這裡要注意的是,雖然用static對局部變量進行修飾過後,其生命周期以及存儲空間發生了變化,但是其作用域并沒有改變,其仍然是一個局部變量,作用域僅限于該語句塊。

#include <iostream>
using namespace std;

void FunTest()
{
    static int i = ;
    int j = ;
    ++i;
    ++j;
    cout<<"i = "<<i<<"  ";
    cout<<"j = "<<j<<endl;

}

int main()
{
    FunTest();
    FunTest();
    FunTest();
    return ;
}
           
static和extern的關系

i是靜态局部變量,沒有在棧上,雖然出了函數但生命周期沒有結束。是以再調用時i從2自增。j是局部變量,随着函數結束就被銷毀了,再次調用時重新初始化。 static雖然可以改變變量的生命周期卻不能改變作用域。

1.2. static 修飾全局變量

test1.cpp中

test2.cpp

#include <iostream>
using namespace std;

extern int i ;
int main()
{

    cout<<i<<endl;
    return ;
}
           

則執行結果為 1

但是如果在file1.c中把int a=1改為static int a=1;那麼在file2.c是無法通路到變量a的。原因在于用static對全局變量進行修飾改變了其作用域的範圍,由原來的整個工程可見變為本源檔案可見。

1.3修飾函數

修飾函數的結果和修飾全局變量一樣,改變函數的作用域。

在檔案域中聲明函數為inline函數預設為static。

extern:

在C語言中,修飾符extern用在變量或者函數的聲明前,用來說明“此變量/函數是在别處定義的,要在此處引用”。

在上面的例子中可以看出,在file2中如果想調用file1中的變量a,隻須用extern進行聲明即可調用a,這就是extern的作用。在這裡要注意extern聲明的位置對其作用域也有關系,如果是在main函數中進行聲明的,則隻能在main函數中調用,在其它函數中不能調用。其實要調用其它檔案中的函數和變量,隻需把該檔案用#include包含進來即可,為啥要用extern?因為用extern會加速程式的編譯過程,這樣能節省時間。

在C++中extern還有另外一種作用,用于訓示C或者C++函數的調用規範。比如在C++中調用C庫函數,就需要在C++程式中用extern “C”聲明要引用的函數。這是給連結器用的,告訴連結器在連結的時候用C函數規範來連結。主要原因是C++和C程式編譯完成後在目标代碼中命名規則不同,用此來解決名字比對的問題.

對于extern變量來說,僅僅是一個變量的聲明,其并不是定義,不會配置設定記憶體空間。

記憶體基本構成

可程式設計記憶體在基本上分為這樣的幾大部分:靜态存儲區、堆區和棧區。他們的功能不同,對他們使用方式也就不同。
           

2.1. 靜态存儲區

記憶體在程式編譯的時候就已經配置設定好,這塊記憶體在程式的整個運作期間都存在。它主要存放靜态資料、全局資料和常量。
           

2.2. 棧區

:在執行函數時,函數内局部變量的存儲單元都可以在棧上建立,函數執行結束時這些存儲單元自動被釋放。棧記憶體配置設定運算内置于處理器的指令集中,效率很高,但是配置設定的記憶體容量有限。

2.3. 堆區

:亦稱動态記憶體配置設定。程式在運作的時候用malloc或new申請任意大小的記憶體,程式員自己負責在适當的時候用free或delete釋放記憶體。動态記憶體的生存期可以由我們決定,如果我們不釋放記憶體,程式将在最後才釋放掉動态記憶體。但是,良好的程式設計習慣是:如果某動态記憶體不再使用,需要将其釋放掉,否則,我們認為發生了記憶體洩漏現象。

2.4.代碼區:存放函數體的二進制代碼。

2.5.文字常量區

在檔案作用域聲明inline函數預設為static存儲類型,const常量預設為static存儲,如果加上extern,則為外部存儲類型。

extern “C”:

主要作用就是為了能夠正确實作C++代碼調用其他C語言代碼。加上extern “C”後,會訓示編譯器這部分代碼按C語言的進行編譯,而不是C++的。由于C++支援函數重載,是以編譯器編譯函數的過程中會将函數的參數類型也加到編譯後的代碼中,而不僅僅是函數名;而C語言并不支援函數重載,是以編譯C語言代碼的函數時不會帶上函數的參數類型,一般之包括函數名。

這個功能十分有用處,因為在C++出現以前,很多代碼都是C語言寫的,而且很底層的庫也是C語言寫的,為了更好的支援原來的C代碼和已經寫好的C語言庫,需要在C++中盡可能的支援C,而extern "C"就是其中的一個政策。
           

這個功能主要用在下面的情況:

1、C++代碼調用C語言代碼

2、在C++的頭檔案中使用

3、在多個人協同開發時,可能有的人比較擅長C語言,而有的人擅長C++,這樣的情況下也會有用到

繼續閱讀