tft每日頭條

 > 生活

 > c語言static 講解

c語言static 講解

生活 更新时间:2024-08-10 01:21:24

找不到出錯原因,讓C 碼農深感受挫;然而讓他們覺得生無可戀的,還是同一段代碼,時而出錯,時而運行良好。 -- 題記

c語言static 講解(CC入門之static是個雷)1

對于初學C /C的人來說,很容易把static修飾符同const修飾符混淆起來。字面上,一個靜态的,一個不變的,意思的确相近。前面講過const,現在有必要系統地講解一下static,來做一個區分。

static在C 中有多層意思。最直觀的理解是,如果修飾一個變量,則該變量在作用域内,隻被定義一次,再定義無效。當然static還有其他涵義。

(一)再定義無效

怎麼理解呢?static變量的生命周期,貫穿整個程序的運行,從被定義的地方開始,直到main函數退出為止。同一個靜态變量的第二次,第三次乃至第N次定義,都不會導緻重新分配内存給變量,也不會修改變量原來的值。看看C /C入門之堆和棧提到的例子:

void f(){

static int i =0;

i ;

cout << "The value of i:" << i << endl;

}

int main(){

f();

f();

}

第一次打印的值是1,第二次打印的值是2。雖然i是一個局部變量,由于有static修飾,它是被存在内存中的靜态區,而不是棧中的,所以不用擔心程序退出後被銷毀。當第二次調用函數f的時候,編譯器碰到static int i=0;的定義,它不會入棧一個新的變量i,而是到靜态内存區去找到變量i。

類的靜态成員适用同樣的規則。

class A{

static int i;

public:

void f(){

i ;

cout << "The value of i:" << i << endl;

}

};

int A::i = 0;

int main(){

A classa;

A classb;

classa.f();

classb.f();

}

打印出來的i的值分别是1和2。另外,由于類的特殊性,類的成員一般不支持在聲明的時候初始化,由static const修飾的int,float/double以及char除外。字符串,數組和結構等,都必須在類外部進行初始化,無論是否有static const或者static修飾。

(二)類的靜态函數成員的局限

類的靜态函數成員,隻能調用類的其他靜态函數,以及隻能訪問類的靜态數據成員。它的調用方式可以是

類名::靜态函數名

對象名.靜态函數名或者對象名->靜态函數名

(三)static用來限制變量作用域

如果在函數外定義一個變量,那麼這個變量就是全局變量,再在這個變量前加static修飾符,變量的涵義發生了變化,static也不再是靜态的意思了。這個時候的變量,變成了一個内部連接,不再為外部可見。static表示内部的意思,正好與extern的意義相反。也就是說,如果在另外一個文件,定義了同名變量,則兩個變量沒有任何關聯(同名變量不能加extern關鍵字,否則去static變量沖突)。

另外,用extern關鍵字修飾局部變量也是毫無意義的。

(四)靜态(全局)變量的加載順序是個雷

為什麼這麼說呢?找不到出錯原因,讓C 碼農深感受挫;然而讓他們覺得生無可戀的,還是同一段代碼,時而出錯,時而運行良好。全局變量的加載順序,就是一個這樣雷。

全局變量定義在一個單一文件當中,它可以被外部文件引用。如果碰巧,兩個定義在不同文件中的全局變量互相之間有依賴關系,而不同文件的加載順序,是編譯器不能保證的,我們将會碰到一場災難。

試看:

//First.cpp

extern int y;

int x = y 1;

//Second.cpp

extern int x;

int y = x 1;

如果First.cpp被先加載,x的值為1,y被先初始化為0,當Second.cpp被加載的時候,y的值為2。

相反,如果Second.cpp先被加載,y的值為1,x被初始化為0,當First.cpp被加載的時候,x的值為2。

進入main之後,x和y的初始值,取決于被加載的順序,而這個順序,是不能被保證的!

有不少有效的辦法,來避免這個情況的出現。最有效的辦法還是,避免靜态對象依賴的出現。

,

更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!

查看全部

相关生活资讯推荐

热门生活资讯推荐

网友关注

Copyright 2023-2024 - www.tftnews.com All Rights Reserved