以前總是對Static聲明的變量(函數(shù)),感到困惑,因?yàn)檎n本中寫的也比較模糊,弄的經(jīng)常搞不懂啥時(shí)候該用靜態(tài)變量。
課堂上,錢老師對這個(gè)問題做了比較透徹的講解,對這個(gè)問題相關(guān)的知識點(diǎn)總結(jié)如下:
對于靜態(tài)成員的作用范圍僅是當(dāng)前CPP文件,這個(gè)限制應(yīng)該僅是編譯器級別的檢查。
通過觀察它的OBJ文件,可以發(fā)現(xiàn),編譯器對靜態(tài)函數(shù)或者變量的名稱做了改變。改變后的名稱中包含了它的作用范圍,類型等信息。
同時(shí),老師用C來模擬了只初始化一次的原理,由此我對靜態(tài)這個(gè)詞感覺了解了很多,為了證實(shí)錢老師將的內(nèi)容。也為了加強(qiáng)自己對知識的理解,在這個(gè)筆記的同時(shí),我對其進(jìn)行反匯編。
static int TestStatic(int nStartIndex, int nEndIndex)
{
static int nsStartNum = nStartIndex; // 只初始化一次
static int nsEndNum = nEndIndex;
printf("%d\t%d\r\n", nsStartNum, nsEndNum);
nsStartNum++;
nsEndNum++;
return 0;
}
int g_nsGoNum = 100; // 見不到這句代碼對應(yīng)的匯編代碼。
int main()
{
for (int n = 0; n < 10; n++)
{
TestStatic(n, 10-n);
}
return 0;
}
程序輸出的結(jié)果表明,參數(shù)只對這兩個(gè)靜態(tài)變量影響了一次,然后再就不起作用了。
OD加載,分析:
00401020 /$ A0 D8984000 mov al, byte ptr [4098D8] ; 檢查標(biāo)記
00401025 |. A8 01 test al, 1
00401027 |. 75 11 jnz short 0040103A
00401029 |. 8B4C24 04 mov ecx, dword ptr [esp+4] ; 初始化靜態(tài)變量
0040102D |. 0C 01 or al, 1 ; 初始化以后,OR標(biāo)記
0040102F |. A2 D8984000 mov byte ptr [4098D8], al
00401034 |. 890D E0984000 mov dword ptr [4098E0], ecx
0040103A |> A8 02 test al, 2
0040103C |. 75 11 jnz short 0040104F
0040103E |. 8B5424 08 mov edx, dword ptr [esp+8] ; 初始化第二個(gè)變量
00401042 |. 0C 02 or al, 2 ; 設(shè)置標(biāo)志二
00401044 |. A2 D8984000 mov byte ptr [4098D8], al
00401049 |. 8915 DC984000 mov dword ptr [4098DC], edx
0040104F |> A1 DC984000 mov eax, dword ptr [4098DC] ; 開始顯示信息
00401054 |. 8B0D E0984000 mov ecx, dword ptr [4098E0]
0040105A |. 50 push eax
0040105B |. 51 push ecx
0040105C |. 68 30704000 push offset < "%d\t%d\r\n">;
00401061 |. E8 2A000000 call <_printf>
很明白了,它用了一個(gè)DOWRD來做標(biāo)志位,初始化了就將對應(yīng)的位做 按位或 運(yùn)算。在初始化前,先檢查對應(yīng)的標(biāo)記是否為 真,如果是,就不再對它進(jìn)行初始化。
如果覺得這個(gè)流程不清晰,可以看下面的流程圖:
