非常詳細的標準C的標記化結構初始化語法說明

2021-07-14 08:51:27 字數 4311 閱讀 2486

對結構體

struct a
有幾種初始化方式:

struct a a1 = ;
或者

struct a a1 =
或者

struct a a1 = ;
核心喜歡用第一種,使用第一種和第二種時,成員初始化順序可變。

標記化結構初始化語法

在linux2.6核心中對結構體的定義形式發生了變化,不再支援原來的定義形式。

1  static struct tty_operations uart_ops =

2 ;

這個宣告採用了標記化結構初始化語法。這種寫法是值得採用的,因為它使驅動程式在結構的定義發生變化時更具有可移植性,並且使**更加緊湊且易讀。標記化的初始化方法允許對結構成員進行重新排列。在某些場合下,將頻繁被訪問的成員放在相同的硬體快取行上,將大大提高效能。

---lld3

標記化結構初始化語法是iso c99的用法

已知乙個結構,定義如下:

struct book

;

c99支援結構的指定初始化專案,其語法與陣列的指定初始化專案近似。只是,結構的指定初始化專案使用點運算子和成員名(而不是方括號和索引值)來標識具體的元素。例如,只初始化book結構的成員vlaue,可以這樣做:

struct book surprise = ;
可以按照任意的順序使用指定初始化專案:

struct book gift = ;
正像陣列一樣,跟在乙個指定初始化專案之後的常規初始化專案為跟在指定成員後的成員提供了初始值。另外,對特定成員的最後一次賦值是它實際獲得的值。例如,考慮如下宣告:

struct book gift = ;

這將把值0.25賦給成員vlaue,因為它在結構宣告中緊跟在author成員之後。新的值0.25代替了早先的賦值18.90。

有關designated initializer的進一步資訊可以參考c99標準的6.7.8節initialization。

**舉例:

#include #include struct operators ;  

void read1(char *data)

void read2(char *data)

void read3(char *data)

int main()

; //所謂的標記化結構初始化語法

struct operators my_op = ;

my_op.read1("wangyang");

my_op.read2("wangyang");

my_op.read3("wangyang");

return 0;

}

重點就在於main()函式中對my_op結構體的初始化語句,使用點加變數名進行初始化。用過python的人會馬上感覺這與關鍵字傳參是多麼的相似。

那它好處在**呢?

我想好處有三。

首先,標記傳參不用理會引數傳遞的順序,正如我上面的例子裡表示的那樣,我是先初始化了read2,然後再初始化了read1,程式設計師不用記憶引數的順序;

再者,我們可以選擇性傳參,在傳統c語言順序傳參中,如果你只想對第三個變數進行初始化,那麼你不得不給第乙個,第二個引數進行初始化,而有時候乙個變數並沒有和合適的預設值,而使用標記初始化法,你可以相當自由地對你有把握的引數進行初始化;

還有,擴充套件性更好,如果你要在該結構體中增加乙個字段,傳統方式下,為了考慮**修改量,你最好將新新增的字段放在這個結構體的最後面,否則你將要面對大量而且無趣的修改,你可能覺得放在**沒什麼關係,但是我們都習慣了,姓名下面是性別,性別下面是年齡,接著是興趣愛好,最後是事蹟描述,如果年齡放在了最後面,難道不彆扭麼?

上面的例程為什麼在vc++6.0中編譯不同通過呢???

在bluedrum的空間中有篇名為《c版本差異 --- 結構處理差別》的第3點中講到:

在標準c中(c89),結構標準初始化是用{}來初始化,在c99的版本,採用了可讀性更強的標記化初始化,這在linux核心和驅動中很為常見。

其中vc++6.0只支援c89初始化,gcc支援自己標記化或自己擴充套件初始化。

struct name_str;

/* 標記式初始化,注意順序不同,並可預設 */

struct name_str str =;

/* c89 初始化 */

struct name_str str2 =

;/* gcc 擴充套件初始化 */

struct name_str str3 =

}

「vc++ 2005 支援的是c89  而不是c99  這點可以在一次對vs2005的負責人的採訪中看出來,他解釋了為什麼vs2005支援c89 而不支援c99  目前完全支援c99標準的編譯器還不存在 支援部分c99標準的編譯器也不多 做的最好的是gcc」

特定的初始化

標準c89需要初始化語句的元素以固定的順序出現,和被初始化的陣列或結構體中的元素順序一樣。

在iso c99中,你可以按任何順序給出這些元素,指明它們對應的陣列的下表或結構體的成員名,並且gnu c也把這作為c89模式下的乙個擴充套件。這個擴充套件沒有在gnu c++中實現。

為了指定乙個陣列下標,在元素值的前面寫上"[index] = "。比如:

int a[6] = ;
相當於:

int a[6] = ;
下標值必須是常量表示式,即使被初始化的陣列是自動的。

乙個可替代的語法是在元素前面寫上".[index]",沒有"=",但從gcc 2.5開始就不再被使用,但gcc仍然接受。為了把一系列的元素初始化化為相同的值,寫為"[first ... ... last] = value"。這是乙個gnu擴充套件。比如:

int widths = ;
如果其中的值有***,這個***將只發生一次,而不是範圍內的每次初始化一次。

注意:陣列的長度是指定的最大值加一。

在結構體的初始化語法中,在元素值的前面用".fieldname = "指定要初始化的成員名。例如,給定下面的結構體:

struct point ;
和下面的初始化:

struct point p = ;
等價於:

struct point p = ;
另一有相同含義的語法是「.fieldname:」,不過從gcc 2.5開始廢除了,就像這裡所示:

struct point p = ;

"[index]"或".fieldname"就是指示符。在初始化共同體時,你也可以使用乙個指示符(或不再使用的冒號語法),來指定共同體的哪個元素應該使用。比如:

union foo ;

union foo f = ;

將會使用第二個元素把4轉換成乙個double型別來在共同體存放。相反,把4轉換成union foo型別將會把它作為整數i存入共同體,既然它是乙個整數。(參考5.24節共同體型別轉換)

int a[6] = ;
等價於

int a[6] = ;
當下標是字元或者屬於enum型別時,標識陣列初始化語句的元素特別有用。例如:

int whitespace[256]

= ;

你也可以在"="前面協商一系列的".fieldname"和"[index]"指示符來指定乙個要初始化的巢狀的子物件;這個列表是相對於和最近的花括號對一致的子物件。比如,用上面的struct point宣告:

struct point ptarray[10] = ;
如同乙個成員被初始化多次,它將從最後一次初始化中取值。如果任何這樣的覆蓋初始化有***,***的發生與否是非指定的。目前,gcc會捨棄它們並產生乙個警告。

標準C的標記化結構初始化語法

以前在看 linux 時,就對它的結構體初始化寫法感到奇怪,所有的初始化 都寫清了變數名,並且變數名前面還有乙個詭異的點。最近學習linux裝置驅動,又遇到了,就查了一下,發現自己的知識果然紕漏不少,此種初始化寫法並不是什麼特殊的 風格,而是所謂的 c語言標記化結構初始化語法 designated ...

c的標記化結構初始化語法

在標準c中 c89 結構標準初始化是用 來實始化,在c99的版本,採用了採用可讀性更強的標記化實始化,這在linux核心和驅動很為常見。這是iso c99的用法。c primer plus第五版中相關章節 已知乙個結構,定義如下 struct book c99支援結構的指定初始化專案,其語法與陣列的...

C 的sstream標準庫詳細介紹

1.sstream標準庫常用於格式轉換。2.c 引入了ostringstream istringstream stringstream這三個類,分別進行流的輸入 輸出 輸入輸出操作.3.標頭檔案 include 4.stringstream中,多次進行轉換的時候,要使用成員函式clear 而通常當我...