|
對結(jié)構(gòu)體
struct a {
int b;
int c;
}
有幾種初始化方式:
struct a a1 = {
.b = 1,
.c = 2
};
或者
struct a a1 = {
b:1,
c:2
}
或者
struct a a1 = {1, 2};
內(nèi)核喜歡用第一種,使用第一種和第二種時,成員初始化順序可變。 標(biāo)記化結(jié)構(gòu)初始化語法 在Linux2.6內(nèi)核中對結(jié)構(gòu)體的定義形式發(fā)生了變化,不再支持原來的定義形式。
1 static struct tty_operations uart_ops =
2 {
3 .open = uart_open,//串口打開
4 .close = uart_close,//串口關(guān)閉
5 .write = uart_write,//串口發(fā)送
6 .put_char = uart_put_char,//...
7 .flush_chars = uart_flush_chars,
8 .write_room = uart_write_room,
9 .chars_in_buffer= uart_chars_in_buffer,
10 .flush_buffer = uart_flush_buffer,
11 .ioctl = uart_ioctl,
12 .throttle = uart_throttle,
13 .unthrottle = uart_unthrottle,
14 .send_xchar = uart_send_xchar,
15 .set_termios = uart_set_termios,
16 .stop = uart_stop,
17 .start = uart_start,
18 .hangup = uart_hangup,
19 .break_ctl = uart_break_ctl,
20 .wait_until_sent= uart_wait_until_sent,
21 #ifdef CONFIG_PROC_FS
22 .read_proc = uart_read_proc, //proc入口讀函數(shù)
23 #endif
24 .tiocmget = uart_tiocmget,
25 .tiocmset = uart_tiocmset,
26 };
---LLD3 標(biāo)記化結(jié)構(gòu)初始化語法是ISO C99的用法 C Primer Plus第五版相關(guān)章節(jié): 已知一個結(jié)構(gòu),定義如下:
struct book
{
char title[MAXTITL];
char author[MAXAUTL];
float value;
};
C99支持結(jié)構(gòu)的指定初始化項目,其語法與數(shù)組的指定初始化項目近似。只是,結(jié)構(gòu)的指定初始化項目使用點運算符和成員名(而不是方括號和索引值)來標(biāo)識具體的元素。例如,只初始化book結(jié)構(gòu)的成員vlaue,可以這樣做:
struct book surprise = { .value = 10.99 };
可以按照任意的順序使用指定初始化項目:
struct book gift = {
.value = 25.99,
.author = "James Broadfool",
.title = "Rue for the Toad"
};
正像數(shù)組一樣,跟在一個指定初始化項目之后的常規(guī)初始化項目為跟在指定成員后的成員提供了初始值。另外,對特定成員的最后一次賦值是它實際獲得的值。例如,考慮如下聲明:
struct book gift = {
.value = 18.90,
.author = "Philionna pestle",
0.25
};
有關(guān)designated initializer的進一步信息可以參考C99標(biāo)準(zhǔn)的6.7.8節(jié)Initialization。 代碼舉例:
#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()
{ //傳統(tǒng)的初始化方法
//struct operators my_op = {read1, read2, read3, 100}; //所謂的標(biāo)記化結(jié)構(gòu)初始化語法
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;
}
那它好處在哪里呢? 我想好處有三。 首先,標(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)記化或自己擴展初始化。
struct name_str{
int data;
char name[120];
int num;
};
/* 標(biāo)記式初始化,注意順序不同,并可缺省 */
struct name_str str ={
.num = 100;
.name = "hxy";
};
/* C89 初始化 */
struct name_str str2 =
{
100,"Andrew Huang",-2
};
/* gcc 擴展初始化 */
struct name_str str3 =
{
name:"bluedrum";
data:-1
}
}
個人想編譯以上代碼,想下個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] = "。比如:
int a[6] = { [4] = 29, [2] = 15 };
相當(dāng)于:
int a[6] = { 0, 0, 15, 0, 29, 0 };
下標(biāo)值必須是常量表達式,即使被初始化的數(shù)組是自動的。 一個可替代的語法是在元素前面寫上".[index]",沒有"=",但從GCC 2.5開始就不再被使用,但GCC仍然接受。為了把一系列的元素初始化化為相同的值,寫為"[first ... ... last] = value"。這是一個GNU擴展。比如:
int widths[] = { [0 ... 9] = 1, [10 ... 99] = 2, [100] = 3 };如果其中的值有副作用,這個副作用將只發(fā)生一次,而不是范圍內(nèi)的每次初始化一次。
注意:數(shù)組的長度是指定的最大值加一。 在結(jié)構(gòu)體的初始化語法中,在元素值的前面用".fieldname = "指定要初始化的成員名。例如,給定下面的結(jié)構(gòu)體:
struct point { int x, y; };和下面的初始化:
struct point p = { .y = yvalue, .x = xvalue };
等價于:
struct point p = { xvalue, yvalue };另一有相同含義的語法是“.fieldname:”,不過從GCC 2.5開始廢除了,就像這里所示:
struct point p = { y: yvalue, x: xvalue };"[index]"或".fieldname"就是指示符。在初始化共同體時,你也可以使用一個指示符(或不再使用的冒號語法),來指定共同體的哪個元素應(yīng)該使用。比如:
union foo { int i; double d; };
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ù)的元素。比如:
int a[6] = { [1] = v1, v2, [4] = v4 };
等價于
int a[6] = { 0, v1, v2, 0, v4, 0 };當(dāng)下標(biāo)是字符或者屬于enum類型時,標(biāo)識數(shù)組初始化語句的元素特別有用。例如:
int whitespace[256]
= { [' '] = 1, ['\t'] = 1, ['\h'] = 1,
['\f'] = 1, ['\n'] = 1, ['\r'] = 1 };你也可以在"="前面協(xié)商一系列的".fieldname"和"[index]"指示符來指定一個要初始化的嵌套的子對象;這個列表是相對于和最近的花括號對一致的子對象。比如,用上面的struct point聲明:
struct point ptarray[10] = { [2].y = yv2, [2].x = xv2, [0].x = xv0 };如同一個成員被初始化多次,它將從最后一次初始化中取值。如果任何這樣的覆蓋初始化有副作用,副作用的發(fā)生與否是非指定的。目前,GCC會舍棄它們并產(chǎn)生一個警告。 |
|
|
來自: Qin Hantang > 《VC》