廢話不多說,直接一步到位來說明吧。
作用
變量前加上static有 兩個 作用:
1、使當前變量的作用域變?yōu)楫斍白兞克x的作用域
2、使當前變量本質上變成全局變量
使當前變量的作用域變?yōu)楫斍白兞克x的作用域
1、修飾全局變量時
話不多說,show the code
直接舉栗子,看下面代碼
#include <iostream>
using namespace std;
//這是一個全局變量。加上static后會讓變量a的作用域限制于main.cpp里
static int a = 10;
int main(int argc, const char * argv[]) {
return 0;
}
從上面代碼知道,這里定義了一個全局變量a。加上static后會讓變量a的作用域限制于main.cpp里??赡苡行┬』锇闀X得很納悶了,這個全局變量a的作用域不就是在main.cpp里嗎?其實呢并不是這樣的,眾所周知,在C/C++里,我們可以直接在其他的文件里通過以下這樣的操作就訪問main.cpp里的全局變量a
我們先在test.cpp里定義并初始化一個全局變量testA:
//test.cpp
#include "test.h"
int testA = 22;
void test()
{
}
之后,我們甚至都可以不在main.cpp里#include "test.h"文件,都可以直接在main.cpp里使用test.cpp里的testA變量,也就是使用extern,代碼如下:
//main.cpp
#include <iostream>
using namespace std;
extern int testA;
int main(int argc, const char * argv[]) {
cout << "testA = " << testA << endl;
return 0;
}
打印結果如下圖

但是,當你在testA變量前加上static的話,就能讓testA變量的作用域被限制在test.cpp內,也就是說,外部再通過extern int testA 的方式就無法testA進行訪問了,在編譯過程中就會直接報錯
代碼如下:
//test.cpp
#include "test.h"
static int testA = 22;
void test()
{
}
報錯截圖如下:

我這里用的是Xcode,他底層會自動將全局變量名加上下劃線,所以這里看到的就是_testA
2、修飾局部變量時
那么如果static本身修飾的就是局部變量呢?
如下代碼:
//test.cpp
#include "test.h"
void test()
{
static int a = 10;
}
其實對于這條規(guī)則仍然適用,仍然會將局部變量a的作用域變?yōu)楫斍岸x的作用域,但是由于當前a定義的作用域就是在test函數里,因此改變之后和改變之前是一樣的(就相當于沒有改變)
使當前變量本質上變成全局變量
1、修飾局部變量時
如下代碼:
//main.cpp
#include <iostream>
using namespace std;
int globalA = 10;
int main(int argc, const char * argv[]) {
int a = 20;
cout << "globalA的地址 = " << & globalA << endl;
cout << "a的地址 = " << & a << endl;
return 0;
}
上面代碼,我們定義了一個全局變量globalA = 10和一個局部變量a = 20。并且對其相應的地址進行了打印
打印結果如下圖:

可以看到:globalA和a的地址值是相差非常大的,因為他們一個是在全局區(qū),一個是在棧區(qū)
我們現在將局部變量a加上static進行修飾,看看結果如何,代碼如下:
//main.cpp
#include <iostream>
using namespace std;
int globalA = 10;
int main(int argc, const char * argv[]) {
static int a = 20;
cout << "globalA的地址 = " << & globalA << endl;
cout << "a的地址 = " << & a << endl;
return 0;
}
打印截圖如下:

從上圖可以看出:加上static修飾后的局部變量a的地址值就跟全局變量globalA的地址值相差4個字節(jié),也就是說,a是緊挨著globalA存儲的
不信可以接著查看他們在內存空間上是不是這樣的,截圖如下:

從上圖紅框里,明顯能夠看出,16進制的0A就是十進制的10,也就是globalA,16進制的14也就是十進制的20,也就是a。明顯能看出來:他們是緊緊挨在一起存儲的,也就是都存儲在了全局區(qū)
從這里終于也能知道一個東西的原因了,那就是為啥被static修飾的局部變量的值可以被重復的訪問和修改
常見的代碼栗子如下:
//main.cpp
#include <iostream>
using namespace std;
void test() {
static int a = 0;
cout << "a = " << a++ << endl;
}
int main(int argc, const char * argv[]) {
for (int i = 0; i < 20; i++) {
test();
}
return 0;
}
打印結果如下:

2、修飾全局變量時
如果static本身是修飾全局變量呢
如下代碼:
//main.cpp
#include <iostream>
using namespace std;
int globalA = 10;
int globalB = 20;
int main(int argc, const char * argv[]) {
cout << "globalA的地址 = " << & globalA << endl;
cout << "globalB的地址 = " << & globalB << endl;
return 0;
}
這里是定一個了兩個全局變量,并且還未對任何一個全局變量用static進行修飾,打印如下:

打印結果很正常,因為兩個都是全局變量,因此就是緊緊挨在一起存儲的。
現在對globalB用static進行修飾,代碼如下:
//main.cpp
#include <iostream>
using namespace std;
int globalA = 10;
static int globalB = 20;
int main(int argc, const char * argv[]) {
cout << "globalA的地址 = " << & globalA << endl;
cout << "globalB的地址 = " << & globalB << endl;
return 0;
}
打印結果如下:

可以看到,打印結果還是和剛才一毛一樣。
其實對于這條規(guī)則仍然適用,仍然會將全局變量的本質變?yōu)槿肿兞?,但是由于當前定義的就是一個全局變量,因此改變之后和改變之前是一樣的(就相當于沒有改變)