jicheng0622

【学习笔记】又一次被C99给坑了之结构体变量初始化问题

0
阅读(16865)

    最近在研究飞思卡尔新出的基于Kinties的底层驱动库Kinetis SDK(飞思卡尔也推底层库了,呵呵,有兴趣的同志们可以去瞅瞅,我抽空也单独写篇文章介绍一下),结果深入研究的时候发现不少难以理解的地方,虽然最后证实是俺才疏学浅了,还是技术底蕴不扎实啊,呵呵,不过飞思卡尔底层库一看就是搞软件的一群人写的,咱们偏硬件的技术宅们可能刚开始不太适应,怎么形容呢,个人的感觉长期搞软件的人写出来的代码经常会搞些华而不实的技巧,而搞硬件人的代码则更偏向于简单直接一目了然,呵呵,有点容易挑起论战的嫌疑。好了,闲话说了不少,还是来正题吧。

    这里挑出一个最新发现的一个让我郁闷半天的小问题展开来聊聊。结构体变量是我们在嵌入式编程中常用到的变量之一,而对其进行初始化也是必不可少的一个操作,但是当我在看飞思卡尔底层库的时候却发现其内部所有的结构体变量初始化的形式时却感到有点奇怪,每个结构体变量在初始化时都指明了其内部成员变量,并且每个成员变量的前面还有一个诡异的点儿(刚开始的确让我有点凌乱,呵呵),如下图所示:

image

image

    说实话之前的确没看到过这种方式,现在想想的确有点孤陋寡闻了,这种初始化方式是在C99标准中新加入的(所以C89是不支持的),美其名曰“标记化结构初始化语法”。在标准C中,C89结构标准初始化是用{}来实始化,在C99的版本,则采用了可读性更强的标记化实始化,这种方式的优势就在于对结构体的初始化不必严格按照定义时的顺序。这带来了极大的灵活性,下面我转一下网上常引用的一个例子具体介绍下这种初始化方法的用法:

已知一个结构,定义如下

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。

    上述例子援引自网络特此声明,呵呵。因为这一个小问题困扰了我半天,不过收获自然也是有的,看来找时间真得好好拜读下C99标准的手册了,之前就遇到过C99标准的兼容问题,结果这次又被它给“坑”了,呵呵。不过还需要强调的是,需要查看下你所使用的编译器是支持哪个版本的标准C的,一般情况下GCC是更新最快的(紧跟大潮流,毕竟都是一群牛人在维护),而比如VC++6.0还是使用的C89的标准。不过我们搞嵌入式常用的IAR,Keil和Codewarrior10.x(CW编译器用的GCC)等一般都可以支持C99的,对IAR来说其缺省的配置如下:

image

    好了,一点小问题我就涛涛不绝的说了这么多,看来以后老了估计是个话唠啊,哈哈,不过这种问题还是不要闲麻烦的把它作为经验笔记记录下来比较好,防止以后类似问题再犯,也可以作为大家的借鉴吧,呵呵。喝口水,再聊,未完待续~