C/C++ static修飾變量時的作用

廢話不多說,直接一步到位來說明吧。

作用

變量前加上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;
}

打印結果如下圖


image.png

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

//test.cpp
#include "test.h"

static int testA = 22;

void test()
{
}

報錯截圖如下:


image.png

我這里用的是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。并且對其相應的地址進行了打印
打印結果如下圖:

image.png

可以看到: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;
}

打印截圖如下:

image.png

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

從上圖紅框里,明顯能夠看出,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;
}

打印結果如下:


image.png
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進行修飾,打印如下:


image.png

打印結果很正常,因為兩個都是全局變量,因此就是緊緊挨在一起存儲的。
現在對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;
}

打印結果如下:


image.png

可以看到,打印結果還是和剛才一毛一樣。

其實對于這條規(guī)則仍然適用,仍然會將全局變量的本質變?yōu)槿肿兞?,但是由于當前定義的就是一個全局變量,因此改變之后和改變之前是一樣的(就相當于沒有改變)

總結

1、使當前變量的作用域變?yōu)楫斍白兞克x的作用域
2、使當前變量本質上變成全局變量
static無論修飾的是局部變量還是全局變量,只要套用這兩句話,結果都是對的
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容