C語言:標記化結構初始化語法

轉載自http://www.cnblogs.com/omenglvrong1/p/4363821.html   


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

#include <stdio.h>   
#include <stdlib.h>   
struct operators   
{   
     void (*read1)(char *);   
     void (*read2)(char *);   
     void (*read3)(char *);   
     int n;   
};   
   
void read1(char *data)   
{   
     printf("read1: %s/n",data);   
}   
void read2(char *data)   
{   
     printf("read2: %s/n",data);   
}   
void read3(char *data)   
{   
     printf("read3: %s/n",data);   
}   
   
int main()   
{    //傳統的初始化方法   
     //struct operators my_op = {read1, read2, read3, 100};    //所謂的標記化結構初始化語法   
     struct operators my_op = {.read2 = read2,   
                               .read1 = read1,   
                               .read3 = read3,   
                               .n = 100};   
     my_op.read1("wangyang");   
     my_op.read2("wangyang");   
     my_op.read3("wangyang");   
     return 0;   
}  


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


那它的好處在哪裏呢?我想好處有三:

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

    其次,我們可以選擇性傳參,在傳統C語言順序傳參中,如果你只想對第三個變量進行初始化,那麼你不得不給第一個, 第二個參數進行初始化,而有時候一個變量並沒有很合適的默認值,而使用標記初始化法,你可以相當自由地對你有把握的參數進行初始化;

    第三,擴展性更好,如果你要在該結構體中增加一個字段,傳統方式下,爲了考慮代碼修改量,你最好將新添加的字段放在這個結構體的最後面,否則你將要面對大量且無趣的修改,你可能覺得放在哪裏沒什麼關係,但是我們都習慣了,姓名下面是性別,性別下面是年齡,接着是興趣愛好,最後是事蹟描述,如果年齡放在了最後面,難道不彆扭麼?!


有人提到,該種語法還有利於提高性能,木有感覺出來,我在這裏就不談這點了。


其實,該種初始化語法並不是什麼新技術,新定義,它就是ISO C99的一個標準用法,也就是說99年就有了,再說Linus也不會去趕什麼時髦的,據說C Primer Plus第五版中提到了這點,不過,我沒有看過該書,遺憾,我是直接投入了面向對象的懷抱。

 

GCC有擴展標記化結構初始化語法,寫法是下面這樣的:

struct operators my_op = {read2 : read2, read1 : read1, read3 : read3,};



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章