11. 全局靜態變量和局部靜態變量


靜態全局變量和靜態局部變量的探索

一、靜態全局變量

1.特點

靜態全局變量具有文件作用域,生命期是所處模塊裝載到所處模塊卸載,處於同一文件中的代碼能直接訪問它,外部文件不能直接訪問。假設寫了如下代碼,編譯通過。

 

 

 

 

 

 

 

現在在同一工程下新建文件,輸入如下代碼,編譯通過,鏈接失敗。

 

 

 

 

 

 

 

 

 

 

如果換成全局變量,則編譯連接成功:

 

 

 

 

 

 

由此可見,在用extern定義變量時,只能在本文件使用,其他文件無法直接訪問。

 

2.機制

靜態全局變量本質上是受編譯器按語法約束的全局變量,如果未初始化,則分配在數據區的未初始化去,如果已初始化,則分配在數據區的已初始化區域。

 

 

 

 

 

 

 

可以觀察到已初始化的靜態全局變量和全局變量地址緊鄰,未初始化的靜態全局變量和全局變量地址緊鄰。已初始化的全局變量和未初始化的全局變量之間有一定差距。

 

3.適用場合

某些數據或函數不想被外部文件訪問時,可定義為靜態全局變量。好處是提供了一定程度的封裝,高內聚、低耦合、分責任。

 

二、靜態局部變量

1.特點

靜態局部變量只能在定義所在作用域內訪問,具有塊作用域,生命期是所處模塊裝載到所處模塊卸載。

假設寫了如下代碼,編譯無法通過,報錯“error C2065: “nTest1”: 未聲明的標識符”:

 

 

 

2.機制

2.1初始化為常量時

寫如下代碼,可以發現靜態全局變量,靜態局部變量,全局變量的地址緊鄰。

 

 

 

 

 

 

2.2初始為變量時

C文件中,編譯不通過:

 

 

 

 

 

 

 

cpp文件可編譯通過(使用VC6)

 

 

 

 

第一次給nTest1賦值時,00427E50處變為1

 

 

 

 

 

單步一次,變為00427E50處變為3

 

 

 

 

再單步一次,變為07

 

 

 

推測每一個bit保存局部靜態變量是否初始化,為0則表示未初始化,1表示已初始化,所以運行時訪問此bit時,為1則跳過初始賦值代碼。

 

照此推測,修改為0,應該會再次賦值:

 

 

 

 

單步,發現確實修改了

 

 

 

 

 

 

繼續單步

 

 

 

 

繼續單步

 

 

 

 

 

照此推測,將00427E50處改為5,則00427E58處會被賦值,其余兩處不會。先手動修改:

 

 

 

 

單步一次:

 

 

 

 

單步兩次:

 

 

 

 

單步三次:

 

 

 

符合推測,所以vc6編譯器用一個bit保存局部靜態變量是否初始化,為0則表示未初始化,1表示已初始化。

 

2.3 編譯器如何控制它跨界訪問

c文件中定義static_ABC的局部靜態變量,更改調用約定,參數,返回值,每次改一個。再去main.obj里搜索static_ABC,發現均無變化,在static_ABC周圍加上花括號,則有變化。

?static_ABC@?3??Foo1@@9@9 2層花括號,函數名Foo1

?static_ABC@?2??Foo1@@9@9 1層花括號

?static_ABC@?1??Foo1@@9@9 無額外層花括號

 

?static_ABC@?3??Foo2@@9@9 2層花括號,函數名2

?static_ABC@?2??Foo2@@9@9 1層花括號

?static_ABC@?1??Foo2@@9@9 無額外層花括號

 

cpp文件中則和返回類型,參數類型,參數個數,調用約定均有關聯。表現如下:

//?static_ABC@?1??Foo1@@YAXXZ@4HA

//?static_ABC@?2??Foo1@@YAXXZ@4HA

//?static_ABC@?3??Foo1@@YAXXZ@4HA

//?static_ABC@?3??Foo1@@YAXH@Z@4HA

//?static_ABC@?3??Foo1@@YAXHH@Z@4HA

//?static_ABC@?3??Foo1@@YAXHHH@Z@4HA

//?static_ABC@?3??Foo1@@YAHHHH@Z@4HA

//?static_ABC@?3??Foo1@@YANHHH@Z@4HA

//?static_ABC@?3??Foo1@@YGNHHH@Z@4HA

//?static_ABC@?3??Foo1@@YINHHH@Z@4HA

//?static_ABC@?3??Foo1@@YANHHHZZ@4HA

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM