1. 程式人生 > >C語言儲存類修飾符和型別限定符

C語言儲存類修飾符和型別限定符

儲存類修飾符

宣告中出現的儲存類修飾符(storage class specifier)用於修改識別符號的連結和對應物件的儲存週期(連結與儲存週期的概念將會在本章後面介紹)。連結(linkage)和儲存週期(storage duration)是C語言中常會遇到的困擾。連結(識別符號的屬性)和儲存週期(物件的屬性)兩者在宣告中都會受相同關鍵字集(儲存類修飾符)的影響。本章後面會介紹物件的儲存週期可以是動態的、靜態的,或已分配的(allocated),而識別符號的連結可以是外部(external)、內部(internal)或不作限定的。類似“靜態連結”或“外部儲存”等說法在C語言中是沒有意義的。注意:物件有儲存週期,而非連結;識別符號有連結,而非儲存週期。
一個宣告中不能出現多個儲存類修飾符。函式識別符號只可以使用儲存類修飾符extern或static。函式引數只可以使用儲存類修飾符register。5種儲存類修飾符的含義如下:
auto
宣告中有修飾符auto的物件,具有動態儲存週期。這種修飾符只能用於函式內的物件宣告。在ANSI C中,預設情況下函式內的物件宣告都有動態的儲存週期,所以不需要使用修飾符auto。
register
當宣告物件有動態儲存週期時,可以使用修飾符register。該關鍵字告訴編譯器,所宣告物件的訪問應該儘量快——理想情況下,應該將該物件儲存在CPU暫存器(register)中。然而,編譯器可能並不會按照理想情況那樣做,而是會把用register宣告的物件當成普通的動態儲存週期物件。不管怎樣,只要採用修飾符re-gister聲明瞭物件,就不能用地址運算子對該物件進行操作。
static
被宣告為static的函式識別符號具有內部連結,換句話說,別的翻譯單元無法使用所宣告的函式識別符號來訪問該函式。
被宣告為static的物件識別符號可能為外部連結,也可能為內部連結,至於是哪一種連結形式,取決於物件的定義是在函式內還是函式外。被宣告為static的物件具有靜態儲存週期。因此,修飾符static允許定義區域性物件(也就是具有語句塊作用域的物件)為具有靜態的儲存週期。
extern
被宣告為extern的函式和物件識別符號具有外部連結。可以在程式中任何地方使用這些識別符號。外部物件具有靜態的儲存週期。
_Thread_local
修飾符_Thread_local宣告物件為執行緒區域性(thread-local),表示每個執行緒都分別具有該物件的例項。只有物件能被宣告為執行緒區域性,而函式不能。如果在函式內部宣告一個執行緒區域性物件,宣告必須具有修飾符extern或static。在一個表示式中,執行緒區域性物件的識別符號引用當前執行緒中物件的本地例項,當前執行緒指當前計算該表示式的執行緒。示例請參見14.4.1節。

型別限定符

可以利用型別限定符修改宣告中的型別,型別限定符有const、volatile、restrict和_Atomic。宣告中可使用多個型別限定符,它們的順序沒有限制。型別限定符列表內可以多次出現相同的型別限定符,或者通過限定typedef名稱的方式,反覆使用同一個限定符。編譯器會忽略重複出現的限定符,將它們視為只出現一次。
各種型別限定符的含義如下:
const
物件的型別如果採用了限定符const,則該物件就是常量。在定義該物件之後,程式無法修改它。
volatile
物件的型別如果採用了限定符volatile,則該物件可以被其他程序或事件修改。關鍵字volatile告訴編譯器在每次使用該物件值時,都要重新讀取它,即便程式本身自上一次獲取後再沒有修改過它的值。這種限定符通常用於硬體介面程式設計,以防止變數值被外部事件修改後,未能及時更新。
restrict
限定符restrict只適用於物件指標型別。這種型別限定符是C99新增加的,用來告訴編譯器,一個被指標所引用的物件,如果它可以被修改,那麼只能被restrict限定的指標修改,不能被除該指標以外的其他任何方式修改,無論是直接方式還是間接方式。該特性允許編譯器採用特定優化技術,而該技術可能需要restrict特性的支撐。編譯器也有可能會忽略限定符restrict,而不對程式結果造成任何影響。
_Atomic
採用型別限定符_Atomic宣告的物件是一個原子物件(atomic object)。陣列不能是原子物件。對原子物件的支援是可選的:C11實現版本中,如果定義了巨集_STDC_NO_ATOMICS_,則表示程式不能宣告原子物件。關於原子物件的詳細介紹,請參見第14章。
編譯器也可以將const物件儲存在記憶體中的只讀區域,但是volatile物件不能。如果程式不使用volatile物件的地址,也有可能編譯器乾脆不為該物件分配記憶體。
物件如果同時使用了限定符const和volatile,如下例中ticks物件所示,它不能被程式本身修改,但可以被其他事件修改,例如時鐘晶片的中斷處理程式:
extern cons