加入星计划,您可以享受以下权益:

  • 创作内容快速变现
  • 行业影响力扩散
  • 作品版权保护
  • 300W+ 专业用户
  • 1.5W+ 优质创作者
  • 5000+ 长期合作伙伴
立即加入
  • 正文
    • 一、应用示例
    • 二、优点和缺点
    • 三、注意事项
  • 推荐器件
  • 相关推荐
  • 电子产业图谱
申请入驻 产业图谱

嵌入式 C 语言特性,指定初始化器

07/18 11:20
999
阅读需 8 分钟
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

我是老温,一名热爱学习的嵌入式工程师关注我,一起变得更加优秀!

在嵌入式 C 语言的 C89/C90 标准里面,要求程序员在初始化程序中的各个变量元素时,要以固定的顺序进行,并且要与被初始化的数组和结构体的元素顺序相同。

在后来的新标准 C99/C11 里面,新增加了一个灵活且好用的特性:指定初始化器(Designated Initialize),这个新特性可以允许程序员在初始化数组或结构体时,可以指定特定的元素初始值,而不需要按照固定的顺序。

一、应用示例

指定初始化器,一般可以应用于数组、结构体、联合体,等成员变量的初始化,以下举例说明一下。

(1)数组:

对于普通数组在定义时的元素初始化,比如初始化最后一个元素为9527,使用传统的 C89 语法和C99语法,它们两者之间的差异,如以下代码所示。

int arr_1[5] = {0, 0, 0, 0, 9527};    //使用传统的C89语法
int arr_2[5] = {[4] = 9527};    //使用C99特性,指定初始化器

以上的使用方法比较好理解,对于未被使用的元素都初始化为0,在旧的C89语法里面,需要按数组元素的顺序进行初始化,而使用了C99语法的指定初始化器,可以指定具体的元素索引进行初始化。

我们再来看一种比较复杂的使用场景:

#include <stdio.h>
int main(void){    int i;    int num[8] = {11, 22, [4] = 55, 66, 77, [1] = 99};
    for (i = 0; i < 8; i++)        printf("index = %2d, num = %dn", i, num[i]);
    return 0;}

程序运行后,具体输出如下:

index = 0, num = 11index = 1, num = 99index = 2, num = 00index = 3, num = 00index = 4, num = 55index = 5, num = 66index = 6, num = 77index = 7, num = 00

从以上的程序运行输出可以看出,使用指定初始化器对数组进行初始化的时候,如果指定的元素后面有更多的值,那么这些值将被用于初始化指定元素后面的元素,num[4]被初始化为55后,num[5] 和 num[6] 会被初始化为 66 和 77。(需要注意定长数组的溢出问题)

再看一下上面的程序,一开始num[1] 被初始化为22,但后面又被重新指定初始化为[1] = 99,前面的初始值22就会被新的指定的初始值99替代。

(2)结构体与联合体

除了数组,C99 特性还为结构体和联合体提供了指定初始化器,在语法上,结构体或联合体在使用指定初始化器的时候,通常使用“点运算符和成员名”来标识特定的元素。

typedef struct student{    char name[20];    int age;    char school[20];    int class;}student_t;
student_t stu_1 = {    .age = 10,    .name = "John",    .school = "lanxiang",    .class = 3,};

从以上的代码可以看出,学生 John 的年龄是10岁,在lanxiang学校就读三年级。结构体的成员可以按照任意数量任意顺序进行初始化。
与数组类似的是,对成员最后一次赋值才是该成员的实际初始化值,如下代码所示,class的值由最后的 5 取代了前面 3,(因为class成员在school后面)。

student_t stu_1 = {    .class = 3,    .school = "lanxiang",    5,};

二、优点和缺点

优点:

1、提高代码可读性:指定初始化器可以直观地看到元素被初始化了特定的值,而不需要按照成员顺序来赋值。

2、减少错误:在初始化大型数组或结构体时,指定初始化器可以减少因顺序错误导致的初始化错误。

3、提高效率:在某些情况下,使用指定初始化器可以减少代码量,提高编码效率。

4、灵活性:可以为数组或结构体中的特定元素赋值,而不必关心其他元素的初始化顺序。

5、易于维护:当需要修改特定元素的初始值时,只需修改对应的初始化表达式,而不需要重新排列整个初始化列表。

缺点:

1、兼容性问题:指定初始化器是C99标准新引入的特性,旧版本的编译器可能无法识别这种初始化方式。

2、易引起混淆:对于不熟悉指定初始化器的程序员来说,当初始化列表很长时,这种初始化方式容易引起混淆。

3、限制性:在使用指定初始化器时,不能跳过未初始化的元素。例如,不能在数组的第0个元素和第2个元素之间直接初始化第1个元素。

4、性能影响:在某些情况下,编译器可能需要额外的工作来处理指定初始化器,这可能会对编译时间或运行时性能产生轻微影响。

三、注意事项

在使用指定初始化器的时候,需要遵循以下注意事项:

1、确保编译器支持:在使用指定初始化器之前,确保你的编译器支持C99或更新的标准。

2、遵循初始化顺序:在使用指定初始化器时,不能跳过未初始化的元素。例如,不能直接初始化数组的第2个元素而忽略第1个元素。

3、注意全局和静态变量:全局和静态变量在程序开始执行前就已经初始化完成,使用指定初始化器可以确保这些变量具有正确的初始值。

4、避免过度使用:指定初始化器虽然提供了灵活性,但过度使用可能会使代码难以理解和维护。应该在适当的情况下使用它,以保持代码的清晰和简洁。

5、注意内存对齐:在使用指定初始化器初始化结构体时,注意内存对齐问题,确保结构体的布局符合预期。

推荐器件

更多器件
器件型号 数量 器件厂商 器件描述 数据手册 ECAD模型 风险等级 参考价格 更多信息
SN74LVC1G17DCKT 1 Texas Instruments Single 1.65-V to 5.5-V buffer with Schmitt-Trigger inputs 5-SC70 -40 to 125

ECAD模型

下载ECAD模型
$0.86 查看
NL17SZ17DFT2G 1 onsemi Single Non-Inverting Buffer with Schmitt Trigger Output, SC-88A (SC-70-5 / SOT-353), 3000-REEL

ECAD模型

下载ECAD模型
$0.19 查看
AST3TQ-T-25.000MHZ-28 1 Abracon Corporation XTAL OSC TCXO 25.0000MHZ LVCMOS
$32.98 查看

相关推荐

电子产业图谱