C和指標 3 9作用域 儲存型別示例

2022-08-20 13:09:08 字數 2542 閱讀 5437

1

int a = 5;2

extern

intb;

3static

intc;45

int d( int

e )6

18...

1924

...25}26

static

inti()

2730 ...

屬於檔案作用域的宣告在預設情況下為external鏈結屬性,所以第1行的a的鏈結屬性為external。

如果b的定義在其他地方,第2行的external關鍵字在技術上並非必需,但在風格上卻是圓環這個關鍵字為好。

第3行的static關鍵字修改了c的預設鏈結屬性,把它改為為internal。

宣告了變數a和b(具有external鏈結屬性)的其他原始檔在使用這兩個變數時實際所訪問的是宣告於此處的兩個變數。但是變數c只能由這個原始檔訪問,因為它具有internal鏈結屬性。

變數a、b、c的儲存型別為靜態,表示它們並不是儲存於堆疊中。因此,這些變數在程式執行之前建立,並一起保持它們的值,直到程式結束。它程式開始執行時,這是a將初始化為5。

這些變數的作用域一直延伸到這個原始檔結束為止,但第7行和第13行宣告的區域性變數a和b在那部分程式中將隱藏同名的靜態變數。因此,這3個變數的作用域為:

a 第1到12行, 第17到29行

b 第2到第6行, 第25到29行

c 第3到第29行

第4行宣告了2個識別符號。d的作用域從第4行直到檔案結束。函式d的定義對於這個原始檔中任何以後想要呼叫 它的函式而言直到了函式原型的作用。作為函式名,d在預設情況下具有external鏈結屬性,所以其他原始檔只有在檔案上存在d的原型,就可以呼叫d。如果我們將函式宣告為static,就可以把它的鏈結屬性從external為改為internal,但這樣做將使其他原始檔不能訪問這個函式。對於函式而言,儲存型別並不是問題,因為**總是儲存於靜態記憶體中。

引數e不具有鏈結屬性,所以我們只能從函式內部通過名字訪問它。它具有自動儲存型別,所以它在函式被呼叫時被創到建,當函式返回時消失。由於區域性變數衝突,它的作用域限於第6到11行,第17到19行以及第23到24行。

第6到8行宣告區域性變數,所以它們的作用域到函式結束為止。它們不具有鏈結屬性,所以它們不能在函式的外部通過名字訪問(這是它們稱為區域性變數的原因)。f的儲存型別是自動,當函式每次被呼叫時,它通過隱匿賦值被初始化為。b的儲存型別是暫存器型別,所以它的初始值是垃圾。g的儲存型別是靜態,所以它在程式的整個執行過程中一直存在。當程式開始執行時,它被初始化為20。當函式每次被呼叫時,它並不會被重新初始化。

第9行的宣告並不需要。這個**塊位於第1行宣告的作用域之內。

第12 和 13行為**塊宣告區域性變數。它們都具有自動儲存型別,不具有鏈結屬性,它們的作用域延伸到第16行。這些變數和先前宣告的a和e不同,而且由於名字衝突,在這個**塊中,以前宣告的同名變數是不能被訪問的。

第14行使全域性變數h在這個**塊內可以被訪問。它具有external鏈結屬性,儲存於靜態記憶體中。這是唯一乙個必須使用external關鍵字的宣告,如果沒有它,h將變成另乙個區域性變數。

第19行和20行用於建立區域性變數(自動、無鏈結屬性、作用域限於本**塊)。這個e和引數e是不同的變數,它和第12行宣告的e也不相同。在這個**塊中,從第11行到18行並無巢狀,所以編譯器可以使用相同的記憶體來儲存兩個**塊中不同的變數e。如果你想讓這兩個**塊的的有表示同乙個變數,那麼你就不應該把它宣告為區域性變數。

最後,第25行宣告了函式i,它具有靜態鏈結屬性。靜態鏈結屬性可以它防止它被這個原始檔之外的任何函式呼叫。事實上,其他的原始檔也可能宣告它自己的函式i,它與這個原始檔的i是不同的函式。i的作用域從它宣告的位置直到這個原始檔結束。函式d不可以呼叫函式i,因為d之前不存在i的原型。

具有external鏈結屬性的實體在其他語言的術語裡稱為全域性實體,所以原始檔中的所有函式均可以被訪問它。只要變數並非宣告於**塊或函式定義內部,它在預設情況下的鏈結屬性即為external。如果乙個變數宣告於**塊內部,在它前面新增external關鍵字將使它所引用的是全域性變數而非區域性變數。

具有external鏈結屬性的實體總是具有靜態儲存型別。全域性變數在程式開始執行前建立,並在程式整個執行過程中始終存在。從屬於函式的區域性變數在函式開始執行時建立,在函式執行完畢後銷毀,但用於執行函式的機器指令在程式的生命週期內一直存在。

區域性變數由函式內部使用,不能被其他函式通過名字引用。它在預設情況下的儲存型別為自動,這是基於兩個原因:其一,當這些變數需要時才為它們分配儲存,這樣可以減少記憶體的總需求量。其二,在堆疊上為它們分配存在可能有效地實現遞迴。如果你覺得讓變數的值在函式的多次呼叫中始終保持原先的值非常重要的話,你可以修改它的儲存型別,把它從自動變數改為靜態變數。

作用域、鏈結屬性和儲存型別總結

變數型別

宣告的位置 

是否存於堆疊

作用域如果宣告為static

全域性所有**塊之外

否從宣告處到檔案尾

不允許從其他原始檔訪問

區域性**塊起始處

是整個**塊

變數不儲存於堆疊中,它的值在程式整個執行期一起保持

形式引數

函式頭部

是整個函式

不允許

C 作用域 鏈結屬性和儲存型別

變數在程式的某個部分宣告時,只能在程式的一定區域內才能訪問,這個區域就成為作用域。作用域分為四種 檔案作用域 函式作用域 塊作用域和原型作用域。編譯器通過變數宣告的位置來確定作用域 當變數在所有 塊之外宣告時就在檔案作用域中,檔案作用域的範圍是從變數宣告處一直到檔案的結束。但如果宣告在 h 檔案中,...

變數儲存型別 作用域

auto 作用域和壽命 只能做區域性變數 在函式內或復合語句內定義的自動變數可以省略auto,而在外部定義的無auto的變數顯然不是自動變數 外部變數,即 全域性變數 的壽命和作用域是全域性的 register 作用域和壽命 同auto,即 區域性可見 分配通用暫存器的條件 1 有空閒的暫存器 2 ...

《C和指標》 儲存型別

變數的儲存型別是指儲存變數值的記憶體型別。變數的儲存型別決定變數何時建立 何時銷毀以及它的值將保持多久。有三個地方可以用於存在變數 普通記憶體 執行時堆疊 硬體暫存器。變數的預設 預設 儲存型別取決於它的宣告位置。凡是在任何 塊之外宣告的變數問題儲存於靜態記憶體中,也就是不屬於堆疊的記憶體,這類變數...