今天在看串口驱动(四)的时候 有这样一个结构体初始化 我很不理解 如下:

static struct s3c24xx_uart_port s3c24xx_serial_ports[NR_PORTS] = {
14  [0] = {
15   .port = {
16    .lock  = SPIN_LOCK_UNLOCKED,
17    .iotype  = UPIO_MEM,
18    .irq  = IRQ_S3CUART_RX0,
19    .uartclk = 0,
20    .fifosize = 16,
21    .ops  = &s3c24xx_serial_ops,
22    .flags  = UPF_BOOT_AUTOCONF,
23    .line  = 0,//端口索引:0
24   }
25  },
26  [1] = {
27   .port = {
28    .lock  = SPIN_LOCK_UNLOCKED,
29    .iotype  = UPIO_MEM,
30    .irq  = IRQ_S3CUART_RX1,
31    .uartclk = 0,
32    .fifosize = 16,
33    .ops  = &s3c24xx_serial_ops,
34    .flags  = UPF_BOOT_AUTOCONF,
35    .line  = 1, //端口索引:1
36   }
37  },
38 #if NR_PORTS > 2
39
40  [2] = {
41   .port = {
42    .lock  = SPIN_LOCK_UNLOCKED,
43    .iotype  = UPIO_MEM,
44    .irq  = IRQ_S3CUART_RX2,
45    .uartclk = 0,
46    .fifosize = 16,
47    .ops  = &s3c24xx_serial_ops,
48    .flags  = UPF_BOOT_AUTOCONF,
49    .line  = 2, //端口索引:2
50   }
51  }
52 #endif
53 };

为什么会在成员函数前加上小数点呢?  我在网上游荡了好一阵找到了“Felix 的博客”,内容如下:

标记化结构初始化语法

在Linux2.6内核中对结构体的定义形式发生了变化,不再支持原来的定义形式。

1  static struct tty_operations uart_ops =
2  {
3   .open  = uart_open,//串口打开
4   .close  = uart_close,//串口关闭
5   .write  = uart_write,//串口发送
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入口读函数
23 #endif
24  .tiocmget = uart_tiocmget,
25  .tiocmset = uart_tiocmset,
26 };

 

这个声明采用了标记化结构初始化语法。这种写法是值得采用的,因为它使驱动程序在结构的定义发生变化时更具有可移植性,并且使代码更加紧凑且易读。标记化的初始化方法允许对结构成员进行重新排列。在某些场合下,将频繁被访问的成员放在相同的硬件缓存行上,将大大提高性能。

----LLD3

查到这里 我发现一个关键字 “这个声明采用了标记化结构初始化语法” 我就搜索“标记化结构初始化语法” 内容如下:

这是ISO C99的用法

C Primer Plus第五版中相关章节:

已知一个结构,定义如下
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语言标记化结构初始化语法

以前在看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");       return0;  }

重点就在于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,};

上面的例程为什么在vc++6.0中编译怎么通不过呢???

在 bluedrum  的空间中有篇 名为《C版本差异--- 结构处理差别》的第3点中讲到:

3、标记化结构初始化语法

在标准C中(C89(结构标准初始化是用{}来实始化,在C99的版本,采用了采用可读性更强的标记化实始化,这在LINUX内核和驱动很为常见。

其中VC++ 6.0只支持C89初始化,GCC支持自己标记化或自己扩展初始化。这种初始化采用 .name = value.这样不需要按顺序排序,方便调整实义,在大结构最大程度防止错位的和调整定义带来不便

struct name_str{
 int data;
 char name[120];
 int num;
};
/* 标记式初始化,注意顺序不同,并可缺省 */
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的负责人的采访中看出来  
  他解释了为什么VS2005支持C89   而不支持C99  
   
  目前完全支持C99标准的编译器还不存在  
  支持部分C99标准的编译器也不多  
  做的最好的是GCC”

查到这里 终于明白这是个怎么回事了

截稿了

原文:标记化结构初始化语法 在结构体成员前加上小数点 如 “.open .write .close ”C99编译器

标记化结构初始化语法 在结构体成员前加上小数点 如 “.open .write .close ”C99编译器 .的更多相关文章

  1. C语言标记化结构初始化语法

    C语言标记化结构初始化语法 (designated initializer),而且还是一个ISO标准. #include <stdio.h> #include <stdlib.h&g ...

  2. 标准C的标记化结构初始化语法

    1 struct file_operations { 2         struct module *owner; 3         loff_t (*llseek) (struct file * ...

  3. C基础--结构体成员初始化方式

    之前在linux内核代码中看到结构体成员成员初始化使用类似于.owner = THIS_MODULE, 不太见过,于是搜了个博客,分享下: 转自:http://www.cnblogs.com/Anke ...

  4. C++结构体成员列表初始化

    C++关于struct和class的区别,可以看上一篇文章:c ++ class和struct[转] 结构体成员列表初始化,来个例子: #include <iostream> #inclu ...

  5. C语言语法教程-结构体

    2018-09-30 结构体中成员变量地址是连续的,结构体用于描述记录. Create a struct //---------------------------- //struct1.c //创建 ...

  6. Delphi XE5教程6:单元的结构和语法

    内容源自Delphi XE5 UPDATE 2官方帮助<Delphi Reference>,本人水平有限,欢迎各位高人修正相关错误! 也欢迎各位加入到Delphi学习资料汉化中来,有兴趣者 ...

  7. 使用XML的五种场合,XML基本规则,XML的术语,结构与语法

    在很多研讨会和培训班上我遇到过许多人,他们还不明白为什么要使用XML也不知道如何 在他们的应用中使用XML.一些来自诸如Gartner公司的报告建议说,商业公司不能再做 局外人了,不能对XML置之不理 ...

  8. FFmpeg源代码简单分析:结构体成员管理系统-AVClass

    ===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...

  9. Delphi XE5教程5:程序的结构和语法

    内容源自Delphi XE5 UPDATE 2官方帮助<Delphi Reference>,本人水平有限,欢迎各位高人修正相关错误! 也欢迎各位加入到Delphi学习资料汉化中来,有兴趣者 ...

随机推荐

  1. python 数据类型 之 集合

    集合是一个数学概念:由一个或多个确定的元素所构成的整体叫做集合 集合的三个特性: 1.确定性 (element必须可hash,不可变类型是可hash的) 2.互异性(集合中element 不能重复) ...

  2. Python中setup.py一些不为人知的技巧

    http://python.jobbole.com/80912/ 在我开始之前,我想先说清楚我将要解释的是些“窍门”.他们不是“最好的做法”,至少在一种情况下是不可取的. 说到不可取的做法,我会适时写 ...

  3. python 标准输入输出sys.stdout. sys.stdin

    import sys, time ## print('please enter your name:')# user_input=sys.stdin.readline()# print(user_in ...

  4. 文章如何做伪原创 SEO大神教你几招做"原创"网站文章的心得

    想要创作出好的文章并被百度所喜欢,就非常需要SEO的优化能力,以及要对文章进行塬创或伪塬创,那么,如何做伪塬创文章?以及如何做好塬创网站文章呢?对此,本文小编就为大家带来了几招做"塬创&qu ...

  5. ASCII、Unicode和UTF-8编码的区别;中英文混合截取

    ASCII编码是128个字符 中国把汉字编入GB2312,Shift_JIS/Euc-kr各国标准..... Unicode是为了解决各国乱码的,但浪费存储空间 UTF-8编码把一个Unicode字符 ...

  6. Oracle_PL/SQL(5) 包

    包1.定义:包用于逻辑组合相关的PL/SQL类型,项和子程序,由包规范和包体组成 建立包规范:包规范是包与应用程序之间的接口,用于定义包的公用组件, 包括常量,变量,游标,过程,函数等 建立包体:用于 ...

  7. Spring Boot 2.0(二):Spring Boot 开源软件都有哪些?(转)

    2016年 Spring Boot 还没有被广泛使用,在网上查找相关开源软件的时候没有发现几个,到了现在经过2年的发展,很多互联网公司已经将 Spring Boot 搬上了生产,而使用 Spring ...

  8. 搭建自己的代理服务 proxy nginx squid ss5 s(shadow)s(socks)

    标签: nginx / squid / 负载均衡 / ss 4090 1. nginx (forward) nginx自己熟悉,经常用来做负载均衡的反向代理, 这里搭建一个正向代理(forward) ...

  9. Android.StructureOfAndroidSourceCodeRootTree

    Refference 1. How to understand the directory structure of android root tree? http://stackoverflow.c ...

  10. WebDriverException:Message:'geckodriver'executable needs to be in Path

    geckodriver是一原生态的第三方浏览器,对于selenium3.x版本都会使用geckodriver来驱动firefox,所以需要下载geckodriver.exe,下载地址:https:// ...