指定初始化
來看看內核用到的指定初始化代碼
在看linux內核源碼時,在源碼中遇到結構體和數組的一種特殊的初始化方法,叫做指定初始化(Designated Initializers),指的是可以對數組中的某些元素或結構體變量中的某些成員以任意的順序進行選擇性的初始化。
如:在linux-3.0.85/arch/arm/mach-s5pv210/mach-smdkv210.c中有這樣一段代碼,
我剛開始看幾乎沒看懂,查了查資料,後分一看開看,原來如此。
/*
struct s3c2410_uartcfg是結構體。
這兒聲明一個結構體數組smdkv210_uartcfgs,並初始化。
__initdata是內核定義的宏,在 include/linux/init.h
#define __initdata __attribute__ ((__section__ (".init.data")))
這個標誌符和變量聲明放在一起,表示gcc編譯器在編譯時,需要把這個變量放在.data.init Section中,
而這個Section 在內核完成初始化之後,會釋放掉。
*/
static struct s3c2410_uartcfg smdkv210_uartcfgs[] __initdata = {
[0] = {
.hwport = 0,
.flags = 0,
.ucon = SMDKV210_UCON_DEFAULT,
.ulcon = SMDKV210_ULCON_DEFAULT,
.ufcon = SMDKV210_UFCON_DEFAULT,
},
[1] = {
.hwport = 1,
.flags = 0,
.ucon = SMDKV210_UCON_DEFAULT,
.ulcon = SMDKV210_ULCON_DEFAULT,
.ufcon = SMDKV210_UFCON_DEFAULT,
},
[2] = {
.hwport = 2,
.flags = 0,
.ucon = SMDKV210_UCON_DEFAULT,
.ulcon = SMDKV210_ULCON_DEFAULT,
.ufcon = SMDKV210_UFCON_DEFAULT,
},
[3] = {
.hwport = 3,
.flags = 0,
.ucon = SMDKV210_UCON_DEFAULT,
.ulcon = SMDKV210_ULCON_DEFAULT,
.ufcon = SMDKV210_UFCON_DEFAULT,
},
};
數組指定初始化
先來看看數組的指定初始化吧。
#include<stdio.h>
void display(int,int *);
int main()
{
/*
傳統的初始化方式
int array[6] = {3,2,0,0,6,0};
或
int array[] = {3,2,0,0,6,0};
或
int array[6];然後循環賦值
*/
//數組的指定初始化
int array1[6] = {[0]=3,[1]=2,[4]=6};
display(6,array1);//輸出: 3 2 0 0 6 0
int array2[6] = {[0]=3,2,[4]=6};
display(6,array2);//輸出: 3 2 0 0 6 0
int array3[6] = {[4]=6,[0]=3,2};
display(6,array3);//輸出: 3 2 0 0 6 0
int array4[] = {[4]=6,0,[0]=3,2};
display(6,array4);//輸出: 3 2 0 0 6 0
//可以看到以上這幾種方式效果一樣
//指定初始化 還可以這樣
int arr5[] = {[0 ... 2]=1,[5]=6};
display(6,arr5);//輸出: 1 1 1 0 0 6
}
void display(int n,int *p)
{
while( n-- ) printf("%d ",*p++);
printf("\n");
}
結構體指定初始化
與傳統初始化比,指定初始化,在小結構體、小數組中可能體現不出優勢,但如你所見,在linux內核代碼中往往結構體比較大,而且絕大多數時候又沒有必要一一賦值,那麼這個時候,結構體的指定初始化優勢就體現出來了。
#include<stdio.h>
typedef unsigned int uint;
struct student
{
uint id;
char *sex;
char *name;
};
void displayStudent(struct student *);
void disStuArray(int,struct student *);
int main()
{
//結構體的指定初始化
struct student stu1={
21,"b","stu1"
};
struct student stu2={
.id = 11,
.sex = "g"
};
struct student stu3={
.name = "stu3",
.sex = "g",
.id = 22
};
displayStudent(&stu1);
displayStudent(&stu2);
displayStudent(&stu3);
}
void displayStudent(struct student *s)
{
printf("學號:%-5d 性別:%-10s 姓名:%-10s \r\n",s->id,s->sex,s->name);
}
把這兩種合起來用
在看完這段代碼後,再回頭看看mach-smdkv210.c中的代碼是不是挺簡單呢。
#include<stdio.h>
typedef unsigned int uint;
struct student
{
uint id;
char *sex;
char *name;
};
void displayStudent(struct student *);
void disStuArray(int,struct student *);
int main()
{
//優勢在這兒,如果這個結構體有幾十個成員,而我有隻需賦值中間某幾個,
//當然了可以先給結構分配內存,在用stu.name = "" 或 p->name=""
//的方式進行賦值,不過這好像麻煩了一點點。
//所以 那什麼 叫指定初始化來着。這就叫指定初始化,
struct student stus[]={
[0] = {21,"g","stu4"},
[3] = {
.id = 22,
.name = "stu5",
.sex = "b"
}
};
disStuArray(4,stus);
}
void displayStudent(struct student *s)
{
printf("學號:%-5d 性別:%-10s 姓名:%-10s \r\n",s->id,s->sex,s->name);
}
void disStuArray(int n,struct student *p)
{
while(n--)
displayStudent(p++);
}