在阅读GNU/Linux内核代码时,我们会遇到一种特殊的结构初始化方式。该方式是某些C教材(如谭二版、K&R二版)中没有介绍过的。这种方式称为指定初始化(designated initializer)。下面我们看一个例子,Linux-2.6.x/drivers/usb/storage/usb.c中有这样一个结构体初始化项目:

static struct usb_driver
usb_storage_driver = {

.owner = THIS_MODULE,

.name = "usb-storage",

.probe = storage_probe,

.disconnect =
storage_disconnect,

.id_table =
storage_usb_ids,

};

乍一看,这与我们之前学过的结构体初始化差距甚远。其实这就是前面所说的指定初始化在Linux设备驱动程序中的一个应用,它源自ISO
C99标准。以下我摘录了C Primer
Plus第五版中相关章节的内容,从而就可以很好的理解2.6版内核采用这种方式的优势就在于由此初始化不必严格按照定义时的顺序。这带来了极大的灵活性,其更大的益处还有待大家在开发中结合自身的应用慢慢体会。

已知一个结构,定义如下

struct book {

char title[MAXTITL];

char author[MAXAUTL];

float value;

};

C99支持结构的指定初始化项目,其语法与数组的指定初始化项目近似。只是,结构的指定初始化项目使用点运算符和成员名(而不是方括号和索引值)来标识具体的元素。例如,只初始化book结构的成员value,可以这样做:

struct book surprise = { .value
= 10.99 };

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

struct book gift = {
.value = 25.99,

.author = "James
Broadfool",

.title = "Rue for the
Toad"};

正像数组一样,跟在一个指定初始化项目之后的常规初始化项目为跟在指定成员后的成员提供了初始值。另外,对特定成员的最后一次赋值是它实际获得的值。例如,考虑下列声明:

struct book gift = { .value =
18.90,

.author = "Philionna
pestle",

0.25};

这将把值0.25赋给成员value,因为它在结构声明中紧跟在author成员之后。新的值0.25代替了早先的赋值18.90。

有关designated initializer的进一步信息可以参考c99标准的6.7.8节Ininialization。

这篇转载大致解决了我们疑惑的问题。其实很简单,绕来绕去的,不就是初始化吗!
  
但是随后又在c语言扩展中找到了如下的起码是我不知道的事情。

标准C89需要初始化语句的元素以固定的顺序出现,和被初始化的数组或结构体中的元素顺序一样。在ISO
C99中,你可以按任何顺序给出这些元素,指明它们对应的数组的下标或结构体的成员名,并且GNU
C也把这作为C89模式下的一个扩展。这个扩展没有在GNU C++中实现。



   为了指定一个数组下标,在元素值的前面写上“[index]
=”。比如:

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



相当于:

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



下标值必须是常量表达式,即使被初始化的数组是自动的。



一个可替代这的语法是在元素值前面写上“.[index]”,没有“=”,但从GCC
2.5开始就不再被使用,但GCC仍然接受。为了把一系列的元素初始化为相同的值,写为“[first ... last] =
value”。这是一个GNU扩展。比如:

int widths[] = { [0 ... 9] = 1, [10 ... 99] = 2, [100] = 3 };



如果其中的值有副作用,这个副作用将只发生一次,而不是范围内的每次初始化一次。



注意,数组的长度是指定的最大值加一。



在结构体的初始化语句中,在元素值的前面用“.fieldname = ”指定要初始化的成员名。例如,给定下面的结构体,

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”就是指示符。在初始化共同体时,你也可以使用一个指示符(或不再使用的冒号语法),来指定共同体的哪个元素应该使用。比如:

union foo { int i; double d; };

        union
foo f = { .d = 4 };



将会使用第二个元素把4转换成一个double类型来在共同体存放。相反,把4转换成union
foo类型将会把它作为整数i存入共同体,既然它是一个整数。(参考5.24节向共同体类型转换。)



你可以把这种命名元素的技术和连续元素的普通C初始化结合起来。每个没有指示符的初始化元素应用于数组或结构体中的下一个连续的元素。比如,

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



等价于

int a[6] = { 0, v1, v2, 0, v4, 0 };



当下标是字符或者属于enum类型时,标识数组初始化语句的元素特别有用。例如:

int whitespace[256]

= { [' '] = 1, ['\t'] = 1, ['\h'] = 1,

['\f'] = 1, ['\n'] = 1, ['\r'] = 1 };



你也可以在“=”前面写上一系列的“.fieldname”和“[index]”指示符来指定一个要初始化的嵌套的子对象;这个列表是相对于和最近的花括号对一致的子对象。比如,用上面的struct
point声明:

struct point ptarray[10] = {
[2].y = yv2, [2].x = xv2, [0].x = xv0 };



如果同一个成员被初始化多次,它将从最后一次初始化中取值。如果任何这样的覆盖初始化有副作用,副作用发生与否是非指定的。目前,gcc会舍弃它们并产生一个警告。

Linux C中结构体初始化的更多相关文章

  1. Linux下C结构体初始化[总结]

    1.前言 今天在公司看一同事写的代码,代码中用到了struct,初始化一个struct用的是乱序格式,如下代码所示: typedef struct _data_t { int a; int b; }d ...

  2. Linux下C结构体初始化

    1.前言 今天在公司看一同事写的代码,代码中用到了struct,初始化一个struct用的是乱序格式,如下代码所示: typedef struct _data_t { int a; int b; }d ...

  3. Linux2.6 内核中结构体初始化(转载)

    转自:http://hnniyan123.blog.chinaunix.net/uid-29917301-id-4989879.html 在Linux2.6版本的内核中,我们经常可以看到下面的结构体的 ...

  4. C语言结构体初始化方法

    早上苏凯童鞋问我这个问题来着,写在这里. 我了解到的C中结构体初始化的方法大概有三种. 如这里我定义了一个结构体: typedef struct node { int x, y; }Node; 第一种 ...

  5. Linux C 结构体初始化三种形式

    最近看linux代码时发现了结构体 struct 一种新的初始化方式,各方查找对比后总结如下: 1. 顺序初始化教科书上讲C语言结构体初始化是按照顺序方式来讲的,没有涉及到乱序的方式.顺序初始化str ...

  6. 关于c语言中结构体的初始化

    1.先定义结构体类型后再定义结构体变量: 格式为:struct 结构体名 变量名列表: struct book s1,s2,*ss://注意这种之前要先定义结构体类型后再定义变量: 2.在定义结构体类 ...

  7. Linux C语言结构体-学习笔记

    Linux C语言结构体简介 前面学习了c语言的基本语法特性,本节进行更深入的学习. 预处理程序. 编译指令: 预处理, 宏定义, 建立自己的数据类型:结构体,联合体,动态数据结构 c语言表达式工具 ...

  8. Linux内核kobject结构体分析

    1.前言 Linux内核中有大量的驱动,而这些驱动往往具有类似的结构,根据面向对象的思想,可以将共同的部分提取为父类,而这个父类就是kobject,kobject结构体中包含了大量设备的必须信息,而三 ...

  9. (一)一个工作任务引起的乱战——c#中结构体与byte[]间相互转换

    一个工作任务涉及到c#与c++系统间的udp通信,处理了蛮长时间没有完成任务,但是期间接触到不少小知识点.本人是初接触c#,c++语言没有接触过.可能写的东西都很小儿科,暂且记录下来当工作日记把. 先 ...

随机推荐

  1. 烂泥:【转】rsync命令参数详解

    本文由秀依林枫提供友情赞助,首发于烂泥行天下. rsync安装完毕后,我们可以通过rsync –help查看rysnc命令的使用.如下: 有关rsync的命令格式,在此我们就不多介绍了.如果有想了解的 ...

  2. 腾讯开放平台 IOS应用URL schema、Boundle ID填写 (含微博、微信)

    解释如下: qq比较麻烦点,需要两个 URL schemes 1.QQ+appID(appid原本是10进制的,需要转换16进制,网址:http://tool.oschina.net/hexconve ...

  3. 初学git,出现错误:fatal: Not a git repository (or any of the parent directories): .git

    提示说没有.git这样一个目录,解决办法: 输入  git init 就可以啦.

  4. Linux rm 删除文件

    rm 删除文件rm -f 强制删除-i 提示-r 删除目录的时候-v 可实话 rm -rfv 多目录 不提示 [root@wang whp]# touch .txt [root@wang whp]# ...

  5. Assembly - Registers

    Processor operations mostly involve processing data. This data can be stored in memory and accessed ...

  6. OpenXml入门---word里面插入图片

    下面介绍如何在word里面插入图片,顺便小弟发现MSDN官网有完整的OpenXML教程,虽然是全英文的不过还是很有帮助的. Tips,原来摘抄代码里面没有模板,在copy过来发现插入word中的图片大 ...

  7. POJ 1556 The Doors【最短路+线段相交】

    思路:暴力判断每个点连成的线段是否被墙挡住,构建图.求最短路. 思路很简单,但是实现比较复杂,模版一定要可靠. #include<stdio.h> #include<string.h ...

  8. c++ learning note

    1/  int 转换成 string 格式 #include<sstream> std::stringstream ss; str::string temp; int n; ss<& ...

  9. HOLOTOOLKIT的使用

    Using HoloToolkit-Unity in Your Project Open or create your project in Unity. Assets -> Import Pa ...

  10. Xbox Live会员身份:银会员和金会员

    推出Xbox360之后,微软重新设计了Xbox Live平台.新设计建立了两个等级的Xbox Live会员身份:银会员和金会员.