插曲關鍵字 static

2021-08-20 10:58:34 字數 4527 閱讀 6139

一,static全域性變數

我們知道,乙個程序在記憶體中的布局如圖1所示:

其中.text段儲存程序所執行的程式二進位制檔案,.data段儲存程序所有的已初始化的全域性變數,.bss段儲存程序未初始化的全域性變數(其他段中還有很多亂七八糟的段,暫且不表)。在程序的整個生命週期中,.data段和.bss段內的資料時跟整個程序同生共死的,也就是在程序結束之後這些資料才會壽終就寢。

當乙個程序的全域性變數被宣告為static之後,它的中文名叫靜態全域性變數。靜態全域性變數和其他的全域性變數的儲存地點並沒有區別,都是在.data段(已初始化)或者.bss段(未初始化)內,但是它只在定義它的原始檔內有效,其他原始檔無法訪問它。所以,普通全域性變數穿上static外衣後,它就變成了新娘,已心有所屬,只能被定義它的原始檔(新郎)中的變數或函式訪問。

以下是一些示例程式

file1.h如下:

[cpp] 

view plain

copy

#include 

void

printstr();  

我們在file1.c中定義乙個靜態全域性變數hello, 供file1.c中的函式printstr訪問.

[cpp] 

view plain

copy

#include "file1.h"

static

char

* hello = 

"hello cobing!"

;  void

printstr()  

file2.c是我們的主程式所在檔案,file2.c中如果引用hello會編譯出錯

[cpp] 

view plain

copy

#include "file1.h"

intmain()  

報錯如下:

[liujx@server235 static]$ gcc -wall file2.c file1.c -o file2

file2.c: in function 『main』:

file2.c:6: 錯誤:『hello』 未宣告 (在此函式內第一次使用)

file2.c:6: 錯誤:(即使在乙個函式內多次出現,每個未宣告的識別符號在其

file2.c:6: 錯誤:所在的函式內只報告一次。)

如果我們將file2.c改為下面的形式:

[cpp] 

view plain

copy

#include "file1.h"

intmain()  

則會順利編譯連線。

執行程式後的結果如下:

[liujx@server235 static]$ gcc -wall file2.c file1.c -o file2

[liujx@server235 static]$ ./file2

hello cobing!

上面的例子中,file1.c中的hello就是乙個靜態全域性變數,它可以被同一檔案中的printstr呼叫,但是不能被不同原始檔中的file2.c呼叫。

二,static區域性變數

普通的區域性變數在棧空間上分配,這個區域性變數所在的函式被多次呼叫時,每次呼叫這個區域性變數在棧上的位置都不一定相同。區域性變數也可以在堆上動態分配,但是記得使用完這個堆空間後要釋放之。

static區域性變數中文名叫靜態區域性變數。它與普通的區域性變數比起來有如下幾個區別:

1)位置:靜態區域性變數被編譯器放在全域性儲存區.data(注意:不在.bss段內,原因見3)),所以它雖然是區域性的,但是在程式的整個生命週期中存在。

2)訪問許可權:靜態區域性變數只能被其作用域內的變數或函式訪問。也就是說雖然它會在程式的整個生命週期中存在,由於它是static的,它不能被其他的函式和原始檔訪問。

3)值:靜態區域性變數如果沒有被使用者初始化,則會被編譯器自動賦值為0,以後每次呼叫靜態區域性變數的時候都用上次呼叫後的值。這個比較好理解,每次函式呼叫靜態區域性變數的時候都修改它然後離開,下次讀的時候從全域性儲存區讀出的靜態區域性變數就是上次修改後的值。

以下是一些示例程式:

file1.h的內容和上例中的相同,file1.c的內容如下:

[cpp] 

view plain

copy

#include "file1.h"

void

printstr()  

為了便於比較,我定義了兩個變數:普通區域性變數normal和靜態區域性變數stat,它們都被賦予初值0;

file2.c中呼叫file1.h:

[cpp] 

view plain

copy

#include "file1.h"

intmain()  

這個呼叫會報錯,因為file2.c中引用了file1.c中的靜態區域性變數stat,如下:

[liujx@server235 static]$ gcc -wall file2.c file1.c -o file2

file2.c: in function 『main』:

file2.c:9: 錯誤:『stat』 未宣告 (在此函式內第一次使用)

file2.c:9: 錯誤:(即使在乙個函式內多次出現,每個未宣告的識別符號在其

file2.c:9: 錯誤:所在的函式內只報告一次。)

編譯器說stat未宣告,這是因為它看不到file1.c中的stat,下面注掉這一行:

[cpp] 

view plain

copy

#include "file1.h"

intmain()  

[liujx@server235 static]$ gcc -wall file2.c file1.c -o file2

[liujx@server235 static]$ ./file2

normal = 0 ---- stat = 0

normal = 0 ---- stat = 1

normal = 0 ---- stat = 2

normal = 0 ---- stat = 3

執行如上所示。可以看出,函式每次被呼叫,普通區域性變數都是重新分配,而靜態區域性變數保持上次呼叫的值不變。

需要注意的是由於static區域性變數的這種特性,使得含靜態區域性變數的函式變得不可重入,即每次呼叫可能會產生不同的結果。這在多執行緒程式設計時可能會成為一種隱患。需要多加注意。

三,static函式

相信大家還記得c++物件導向程式設計中的private函式,私有函式只有該類的成員變數或成員函式可以訪問。在c語言中,也有「private函式」,它就是接下來要說的static函式,完成物件導向程式設計中private函式的功能。

當你的程式中有很多個原始檔的時候,你肯定會讓某個原始檔只提供一些外界需要的介面,其他的函式可能是為了實現這些介面而編寫,這些其他的函式你可能並不希望被外界(非本原始檔)所看到,這時候就可以用static修飾這些「其他的函式」。

所以static函式的作用域是本原始檔,把它想象為物件導向中的private函式就可以了。

下面是一些示例:

file1.h如下:

[cpp] 

view plain

copy

#include 

static

intcalled();  

void

printstr();  

file1.c如下:

[cpp] 

view plain

copy

#include "file1.h"

static

intcalled()  

void

printstr()  

file2.c中呼叫file1.h中宣告的兩個函式,此處我們故意呼叫called():

[cpp] 

view plain

copy

#include "file1.h"

intmain()  

編譯時會報錯:

[liujx@server235 static]$ gcc -wall file2.c file1.c -o file2

file1.h:3: 警告:『called』 使用過但從未定義

/tmp/ccylubzu.o: in function `main':

file2.c:(.text+0x12): undefined reference to `called'

collect2: ld 返回 1

因為引用了file1.h中的static函式,所以file2.c中提示找不到這個函式:undefined reference to 'called'

下面修改file2.c:

[cpp] 

view plain

copy

#include "file1.h"

intmain()  

編譯執行:

[liujx@server235 static]$ gcc -wall file2.c file1.c -o file2

[liujx@server235 static]$ ./file2

returnval=6

static函式可以很好地解決不同原檔案中函式同名的問題,因為乙個原始檔對於其他原始檔中的static函式是不可見的。

this關鍵字 static關鍵字

1.當成員變數和區域性變數重名,可以用關鍵字this來區分 this 代表物件,代表那個物件呢?當前物件 this就是所在函式所屬物件的引用 簡單說 那個物件呼叫了this所在的函式,this就代表哪個物件 this也可以用於在建構函式中呼叫其他建構函式 注意 只能定義在建構函式的第一行,因為初始化...

Java this關鍵字,static關鍵字

1,this.屬性,this.方法,表示當前物件的屬性,當前類的方法 2,this,表示當前物件,當前正在操作這個方法的物件就是當前物件 3,使用this 引數若干 可以呼叫當前類的構造方法,如果,構造方法之間相互呼叫,則有要求 一 this 必須放在首行,二 至少有乙個構造方法是沒有呼叫this ...

static關鍵字 final 關鍵字

特點 隨著類的載入而載入,也就是說靜態會隨著類的消失而消失,說明他的生命週期最長 靜態變數 static 關鍵字修飾成員變數,使用 類名.變數名 的形式來訪問,也可以使用 例項物件.變數名 的形式來訪問。靜態方法 static 關鍵字修飾成員函式,靜態方法可以使用 類名.方法名 的形式來訪問,也可以...