html
函數和變量的聲明不會分配內存, 可是定義會分配相應的內存空間ios
函數和變量的聲明能夠有不少次, 可是定義最多隻能有一次函數
函數的聲明和定義方式默認都是 extern 的, 即函數默認是全局的spa
變量的聲明和定義方式默認都是局部的, 在當前編譯單元或者文件內可用htm
瞭解聲明和定義對static和extern的理解有輔助做用。好比extern就是在一處定義,其餘文件都只須要聲明便可,不可重複定義。blog
通常局部變量是存儲在棧區的,局部變量的生命週期在其所在的語句塊執行結束時便結束了。但若是用static修飾局部變量,那麼這個變量就不會存儲在棧區而是放在靜態數據區,其生命週期會一直持續到整個程序結束,該變量只在初次運行時進行初始化,且只進行一次,可是它的做用域只能是在函數裏面以下:生命週期
void print(){ static int z = 100; z++; cout << z <<endl; } int main(){ print(); print(); print(); return 0; }
局部靜態變量z只能在本文件的print函數裏面訪問,一旦超出做用域範圍,就沒法訪問。內存
若是是static修飾的全局變量,且實現的函數寫在頭文件(h)中,在其餘文件也能夠訪問,以下:作用域
// a.h #ifndef A_H #define A_H #include<iostream> using namespace std; static char str[] = "hello"; namespace sextern { void print1(); void Fun1(); void Fun1(){ str[0] = 'l'; } void print1(){ cout << "value " << str <<endl; cout << "address " << &str <<endl; } } #endif // A_H //b.h #ifndef B_H #define B_H namespace sextern{ void Fun2(){ str[0] = 'o'; } void print2(){ cout << "value " << str <<endl; cout << "address " << &str <<endl; } #endif // B_H //main.cpp #include "a.h" #include "b.h" using namespace sextern; int main(int argc, char *argv[]) { sextern::Fun1(); print1(); sextern::Fun2(); print2(); print1(); return 0; } //結果以下 /* * value lello * address 0x601058 * value oello * address 0x601058 * value oello * address 0x601058 * 按 <RETURN> 來關閉窗口... */
發現將static全局變量寫在頭文件中,全部文件的頭文件的操做都會共享這個變量。get
但若是是在源文件(cpp)中去操做這個靜態全局變量,則這個靜態全局變量只能在當前文件有效,可是在另一個文件訪問此靜態變量,會是該變量初始的默認值,不會是其餘文件中修改的值,雖然它們有相同的初始內容,可是存儲的物理地址並不同。以下:
//a.h #ifndef A_H #define A_H #include<iostream> using namespace std; static char str[] = "hello"; namespace sextern { void Fun1(); void print1(); } #endif // A_H //a.cpp #include "a.h" namespace sextern { void Fun1(){ str[0] = 'l'; } void print1(){ cout << "value " << str << endl; cout << "address " << &str <<endl; } } //c.h #ifndef C_H #define C_H #include<iostream> using namespace std; namespace sextern { void Fun3(); void print3(); } #endif // C_H //c.cpp #include "c.h" #include "a.h" namespace sextern { void Fun3(){ str[0] = 'o'; } void print3(){ cout << "value " << str <<endl; cout << "address " << &str <<endl; } } #include "a.h" #include "c.h" using namespace sextern; int main(int argc, char *argv[]) { sextern::Fun1(); print1(); sextern::Fun3(); print3(); print1(); return 0; } //結果以下 /* * value lello * address 0x602064 * value oello * address 0x60205e * value lello * address 0x602064 * 按 <RETURN> 來關閉窗口... */
在a.h的頭文件中定義了一個靜態的全局變量x,不一樣文件的函數fun1和fun3會爲每一個包含該頭文件的cpp都建立一個全局變量,但他們都是獨立的,只在該cpp文件共享該變量。因此通常定義static全局變量時,都把它放在原文件中而不是頭文件,從而避免多個源文件共享,就不會給其餘模塊形成沒必要要的信息污染。若是想要在不一樣文件共享同一個全局變量,這個時候就要用到extern。
當在某個文件定義了一個全局變量,若是要在另外一個文件去使用該變量,若是再次去定義,則會出現重複定義的問題,這個時候就須要使用到聲明,對該變量的聲明告訴編譯器該變量在其餘文件中已經定義,在此處要去引用它。上述的代碼改爲以下形式:
//b.h #ifndef B_H #define B_H char str[] = "hello"; //定義一個全局變量 #endif // B_H //a.h #ifndef A_H #define A_H #include<iostream> using namespace std; extern char str[]; namespace sextern { void Fun1(); void print1(); } #endif // A_H //a.cpp #include "a.h" namespace sextern { void Fun1(){ str[0] = 'l'; } void print1(){ cout << "value " << str << endl; cout << "address " << &str <<endl; } } //c.h #ifndef C_H #define C_H #include<iostream> using namespace std; extern char str[]; namespace sextern { void Fun3(); void print3(); } #endif // C_H //c.cpp #include "c.h" namespace sextern { void Fun3(){ str[0] = 'o'; } void print3(){ cout << "value " << str <<endl; cout << "address " << &str <<endl; } } //結果以下 /* * value lello * address 0x602058 * value oello * address 0x602058 * value oello * address 0x602058 * 按 <RETURN> 來關閉窗口... */