小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

標(biāo)記化結(jié)構(gòu)初始化語法---結(jié)構(gòu)體成員前加小數(shù)點

 Qin Hantang 2012-09-20

對結(jié)構(gòu)體

  1. struct a {
  2. int b;
  3. int c;
  4. }

有幾種初始化方式:

  1. struct a a1 = {
  2. .b = 1,
  3. .c = 2
  4. };

或者

  1. struct a a1 = {
  2. b:1,
  3. c:2
  4. }

或者

  1. struct a a1 = {1, 2};

內(nèi)核喜歡用第一種,使用第一種和第二種時,成員初始化順序可變。

標(biāo)記化結(jié)構(gòu)初始化語法

在Linux2.6內(nèi)核中對結(jié)構(gòu)體的定義形式發(fā)生了變化,不再支持原來的定義形式。

  1. 1 static struct tty_operations uart_ops =
  2. 2 {
  3. 3 .open = uart_open,//串口打開
  4. 4 .close = uart_close,//串口關(guān)閉
  5. 5 .write = uart_write,//串口發(fā)送
  6. 6 .put_char = uart_put_char,//...
  7. 7 .flush_chars = uart_flush_chars,
  8. 8 .write_room = uart_write_room,
  9. 9 .chars_in_buffer= uart_chars_in_buffer,
  10. 10 .flush_buffer = uart_flush_buffer,
  11. 11 .ioctl = uart_ioctl,
  12. 12 .throttle = uart_throttle,
  13. 13 .unthrottle = uart_unthrottle,
  14. 14 .send_xchar = uart_send_xchar,
  15. 15 .set_termios = uart_set_termios,
  16. 16 .stop = uart_stop,
  17. 17 .start = uart_start,
  18. 18 .hangup = uart_hangup,
  19. 19 .break_ctl = uart_break_ctl,
  20. 20 .wait_until_sent= uart_wait_until_sent,
  21. 21 #ifdef CONFIG_PROC_FS
  22. 22 .read_proc = uart_read_proc, //proc入口讀函數(shù)
  23. 23 #endif
  24. 24 .tiocmget = uart_tiocmget,
  25. 25 .tiocmset = uart_tiocmset,
  26. 26 };


這個聲明采用了標(biāo)記化結(jié)構(gòu)初始化語法。這種寫法是值得采用的,因為它使驅(qū)動程序在結(jié)構(gòu)的定義發(fā)生變化時更具有可移植性,并且使代碼更加緊湊且易讀。標(biāo)記化的初始化方法允許對結(jié)構(gòu)成員進行重新排列。在某些場合下,將頻繁被訪問的成員放在相同的硬件緩存行上,將大大提高性能。

---LLD3

標(biāo)記化結(jié)構(gòu)初始化語法是ISO C99的用法

C Primer Plus第五版相關(guān)章節(jié):

已知一個結(jié)構(gòu),定義如下:

  1. struct book
  2. {
  3. char title[MAXTITL];
  4. char author[MAXAUTL];
  5. float value;
  6. };

C99支持結(jié)構(gòu)的指定初始化項目,其語法與數(shù)組的指定初始化項目近似。只是,結(jié)構(gòu)的指定初始化項目使用點運算符和成員名(而不是方括號和索引值)來標(biāo)識具體的元素。例如,只初始化book結(jié)構(gòu)的成員vlaue,可以這樣做:

  1. struct book surprise = { .value = 10.99 };

可以按照任意的順序使用指定初始化項目:

  1. struct book gift = {
  2. .value = 25.99,
  3. .author = "James Broadfool",
  4. .title = "Rue for the Toad"
  5. };

正像數(shù)組一樣,跟在一個指定初始化項目之后的常規(guī)初始化項目為跟在指定成員后的成員提供了初始值。另外,對特定成員的最后一次賦值是它實際獲得的值。例如,考慮如下聲明:

  1. struct book gift = {
  2. .value = 18.90,
  3. .author = "Philionna pestle",
  4. 0.25
  5. };


這將把值0.25賦給成員vlaue,因為它在結(jié)構(gòu)聲明中緊跟在author成員之后。新的值0.25代替了早先的賦值18.90。

有關(guān)designated initializer的進一步信息可以參考C99標(biāo)準(zhǔn)的6.7.8節(jié)Initialization。

代碼舉例:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. struct operators
  4. {
  5. void (*read1)(char *);
  6. void (*read2)(char *);
  7. void (*read3)(char *);
  8. int n;
  9. };
  10. void read1(char *data)
  11. {
  12. printf("read1: %s/n",data);
  13. }
  14. void read2(char *data)
  15. {
  16. printf("read2: %s/n",data);
  17. }
  18. void read3(char *data)
  19. {
  20. printf("read3: %s/n",data);
  21. }
  22. int main()
  23. { //傳統(tǒng)的初始化方法
  24. //struct operators my_op = {read1, read2, read3, 100}; //所謂的標(biāo)記化結(jié)構(gòu)初始化語法
  25. struct operators my_op = {.read2 = read2,
  26. .read1 = read1,
  27. .read3 = read3,
  28. .n = 100};
  29. my_op.read1("wangyang");
  30. my_op.read2("wangyang");
  31. my_op.read3("wangyang");
  32. return 0;
  33. }


重點就在于main()函數(shù)中對my_op結(jié)構(gòu)體的初始化語句,使用點加變量名進行初始化。用過Python的人會馬上感覺這與關(guān)鍵字傳參是多么的相似。

那它好處在哪里呢?

我想好處有三。

首先,標(biāo)記傳參不用理會參數(shù)傳遞的順序,正如我上面的例子里表示的那樣,我是先初始化了read2,然后再初始化了read1,程序員不用記憶參數(shù)的順序;

再者,我們可以選擇性傳參,在傳統(tǒng)C語言順序傳參中,如果你只想對第三個變量進行初始化,那么你不得不給第一個,第二個參數(shù)進行初始化,而有時候一個變量并沒有和合適的默認值,而使用標(biāo)記初始化法,你可以相當(dāng)自由地對你有把握的參數(shù)進行初始化;

還有,擴展性更好,如果你要在該結(jié)構(gòu)體中增加一個字段,傳統(tǒng)方式下,為了考慮代碼修改量,你最好將新添加的字段放在這個結(jié)構(gòu)體的最后面,否則你將要面對大量而且無趣的修改,你可能覺得放在哪里沒什么關(guān)系,但是我們都習(xí)慣了,姓名下面是性別,性別下面是年齡,接著是興趣愛好,最后是事跡描述,如果年齡放在了最后面,難道不別扭么?

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

在bluedrum的空間中有篇名為《C版本差異 --- 結(jié)構(gòu)處理差別》的第3點中講到:

在標(biāo)準(zhǔn)C中(C89),結(jié)構(gòu)標(biāo)準(zhǔn)初始化是用{}來初始化,在C99的版本,采用了可讀性更強的標(biāo)記化初始化,這在Linux內(nèi)核和驅(qū)動中很為常見。

其中VC++6.0只支持C89初始化,GCC支持自己標(biāo)記化或自己擴展初始化。

  1. struct name_str{
  2. int data;
  3. char name[120];
  4. int num;
  5. };
  6. /* 標(biāo)記式初始化,注意順序不同,并可缺省 */
  7. struct name_str str ={
  8. .num = 100;
  9. .name = "hxy";
  10. };
  11. /* C89 初始化 */
  12. struct name_str str2 =
  13. {
  14. 100,"Andrew Huang",-2
  15. };
  16. /* gcc 擴展初始化 */
  17. struct name_str str3 =
  18. {
  19. name:"bluedrum";
  20. data:-1
  21. }
  22. }

個人想編譯以上代碼,想下個C99編譯器,在百度搜索 C99編譯器,解決時間:2009-07-10 21:54回答是

“VC++ 2005 支持的是C89 而不是C99 這點可以在一次對VS2005的負責(zé)人的采訪中看出來,他解釋了為什么VS2005支持C89 而不支持C99 目前完全支持C99標(biāo)準(zhǔn)的編譯器還不存在 支持部分C99標(biāo)準(zhǔn)的編譯器也不多 做的最好的是GCC”


特定的初始化

標(biāo)準(zhǔn)C89需要初始化語句的元素以固定的順序出現(xiàn),和被初始化的數(shù)組或結(jié)構(gòu)體中的元素順序一樣。

在ISO C99中,你可以按任何順序給出這些元素,指明它們對應(yīng)的數(shù)組的下表或結(jié)構(gòu)體的成員名,并且GNU C也把這作為C89模式下的一個擴展。這個擴展沒有在GNU C++中實現(xiàn)。

為了指定一個數(shù)組下標(biāo),在元素值的前面寫上"[index] = "。比如:

  1. int a[6] = { [4] = 29, [2] = 15 };

相當(dāng)于:

  1. int a[6] = { 0, 0, 15, 0, 29, 0 };

下標(biāo)值必須是常量表達式,即使被初始化的數(shù)組是自動的。

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

  1. int widths[] = { [0 ... 9] = 1, [10 ... 99] = 2, [100] = 3 };
如果其中的值有副作用,這個副作用將只發(fā)生一次,而不是范圍內(nèi)的每次初始化一次。

注意:數(shù)組的長度是指定的最大值加一。

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

  1. struct point { int x, y; };
和下面的初始化:

  1. struct point p = { .y = yvalue, .x = xvalue };
等價于:

  1. struct point p = { xvalue, yvalue };
另一有相同含義的語法是“.fieldname:”,不過從GCC 2.5開始廢除了,就像這里所示:

  1. struct point p = { y: yvalue, x: xvalue };

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

  1. union foo { int i; double d; };
  2. union foo f = { .d = 4 };
將會使用第二個元素把4轉(zhuǎn)換成一個double類型來在共同體存放。相反,把4轉(zhuǎn)換成union foo類型將會把它作為整數(shù)i存入共同體,既然它是一個整數(shù)。(參考5.24節(jié)共同體類型轉(zhuǎn)換)

你可以把這種命名元素的技術(shù)和連續(xù)元素的普通C初始化結(jié)合起來。每個沒有指示符的初始化元素應(yīng)用于數(shù)組或結(jié)構(gòu)體中的下一個連續(xù)的元素。比如:

  1. int a[6] = { [1] = v1, v2, [4] = v4 };

等價于

  1. int a[6] = { 0, v1, v2, 0, v4, 0 };
當(dāng)下標(biāo)是字符或者屬于enum類型時,標(biāo)識數(shù)組初始化語句的元素特別有用。例如:

  1. int whitespace[256]
  2. = { [' '] = 1, ['\t'] = 1, ['\h'] = 1,
  3. ['\f'] = 1, ['\n'] = 1, ['\r'] = 1 };
你也可以在"="前面協(xié)商一系列的".fieldname"和"[index]"指示符來指定一個要初始化的嵌套的子對象;這個列表是相對于和最近的花括號對一致的子對象。比如,用上面的struct point聲明:

  1. struct point ptarray[10] = { [2].y = yv2, [2].x = xv2, [0].x = xv0 };
如同一個成員被初始化多次,它將從最后一次初始化中取值。如果任何這樣的覆蓋初始化有副作用,副作用的發(fā)生與否是非指定的。目前,GCC會舍棄它們并產(chǎn)生一個警告。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多