C语言指定初始化器解析及其应用

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介:

C语言指定初始化器解析及其应用

指定初始化器的概念
C90 标准要求初始化程序中的元素以固定的顺序出现,与要初始化的数组或结构体中的元素顺序相同。但是在新标准 C99 中,增加了一个新的特性:指定初始化器。利用该特性可以初始化指定的数组或者结构体元素。

数组的指定初始化器#
一维数组的指定初始化器#
利用指定初始化器的特性,我们可以这样定义并初始化一个数组:

Copy
int a[6] = {[4] = 10,[2] = 25};
上述的初始化就等同于如下方式:

Copy
int a[6] = {0,0,25,0,10,0};
可以看到通过这种方式能够不按照顺序,且指定具体的元素进行初始化。
除了上述这样的用法,我们也能够初始化数组内一段范围内的用元素,比如这样:

Copy
int a[5] = {[4] = 10,[0 ... 3] = 23};
上面这段程序的初始化也就等同于如下初始化:

Copy
int a[5] = {23,23,23,23,10};
那如果数组初始化里有指定的元素初始化又有未指定的元素又是如何分析呢?比如这样:

Copy
int a[5] = {11,[3] = 44,55,[1] = 22,33};
那它等同于下面的代码:

Copy
int a[5] = {11,22,33,44,55};
如果定义数组时没有指定数组的大小,那么数组实际的大小又是多少呢?比如这样:

Copy
int main(void)
{

int number[] = {[20] = 1,[10] = 8,9};
int n = sizeof(number)/sizeof(number[0]);
printf("The Value of n is:%d\n",n);
AI 代码解读

}
输出结果是这样的:

Copy
The Value of n is:21
也就是说,如果未给出数组的大小,则最大的初始化位置确定数组的大小

二维数组的指定初始化器#
二维数组同样可以采用指定初始化器的方法,下面是一个二维数组的初始化:

Copy
int array2 =
{

[0] = {[0] = 11},
[1] = {[1] = 22},
AI 代码解读

};
这样的初始化也就等同于下述代码:

Copy
int array12 =
{

{11,00},
{00,22}
AI 代码解读

};
通过上述代码,我们也可以知道,二维数组的指定初始化器的方法中,第一个[]里的数字表示的是初始化的二维数组的行数,而在{}内的则是对当前行的元素进行初始化,实际也就是说{}内的初始化方法也就和一维数组的一样了,一维数组可行的方法,二维数组也是可行的。

应用#
在讲述了数组指定初始化器的基本概念之后,我们来看一个具体的例子,下面这个例子是基于状态机的编程方法实现的 ATM 机器,首先 ATM 具有如下几种状态;

我们就可以使用状态机的思路来编写这个程序,首先使用枚举的方式来定义各个状态和相应的操作:

Copy
typedef enum
{

Idle_State,
Card_Inserted_State,
Pin_Entered_State,
Option_Selected_State,
Amount_Entered_State,
last_State
AI 代码解读

}eSysyemState;

typedef enum
{

Card_Insert_Event,
Pin_Enter_Event,
Option_Selection_Event,
Amount_Enter_Event,
Amount_Dispatch_Event,
last_Event
AI 代码解读

}eSystemEvent;
然后是对应操作的具体实现:

Copy
eSysyemState AmountDispatchHandler(void)
{

return Idle_State;
AI 代码解读

}

eSysyemState EnterAmountHandler(void)
{

return Amount_Entered_State;
AI 代码解读

}

eSysyemState OptionSelectionHandler(void)
{

return Option_Selected_State;
AI 代码解读

}

eSysyemState InsertCardHandle(void)
{

return Card_Inserted_State;
AI 代码解读

}

eSysyemState EnterPinHandler(void)
{

return Pin_Entered_State;   
AI 代码解读

}
为了使得状态机的实现看起来不是那么的冗长,我们这里采用查表的方式,首先重定义一个函数指针二维数组类型:

Copy
typedef eSysyemState (* const afEventHandlerlast_State)(void);
简单说一个这是一个二维数组,二维数组里面存放的是函数指针,这个函数指针指向的是返回值为 eSysyemState,形参为 void 的函数。
在重定义了这个类型之后,我们就可以用其定义新的变量了,在这之前,补充一点数组相关的内容,比如有如下代码:

Copy
typedef int array[3];
array data;
那么上述代码也就等同于如下代码:

Copy
int data[3];
有了上述代码之后,我们就可以实现我们的查找表了,具体代码如下:

Copy

static afEventHandler StateMachine = 
{
    [Idle_State] = {[Card_Insert_Event] = InsertCardHandle},
    [Card_Inserted_State] = {[Pin_Enter_Event] = EnterPinHandler },
    [Pin_Entered_State] = {[Option_Selection_Event] = OptionSelectionHandler},
    [Option_Selected_State] = {[Amount_Entered_Event] = EnterAmountHandler},
    [Amount_Entered_State] = {[Amount_Dispatch_Event] = AmountDispatchHandler},
};
AI 代码解读

现在再来看到这个初始化的方法也就比较清楚了,这实际上也就是一个二维数组使用指定初始化器解析的方法,最后,也就是我们的状态机运行代码:

Copy

include

int main(void)
{

eSysyemState eNextState = Idle_State;
eSystemEvent eNewEvent;
while(1)
{
    eNewEvent = ReadEvent();
    /*省略相关判断*/
    eNextState = (*StateMachine[eNextState][eNewEvent])();
}
return 0;
AI 代码解读

}
结构体的指定初始化器#
定义了如下结构体:

Copy
struct point
{

int x,y;
AI 代码解读

}
那么对于结构体变量的初始化可以采用以下的方式:

Copy
struct point p =
{

.y = 2,
.x = 3
AI 代码解读

};
上述代码也就等价于如下代码:

Copy
struct point p = {3,2};
那这样的初始化有什么作用呢?下面是 linux 内核的一段代码:

Copy
const struct file_operations eeprom_fops =
{
.llseek = eeprom_lseek,
.read = eeprom_read,
.write = eeprom_write,
.open = eeprom_open,
.release = eeprom_close
};
上述就是通过指定初始化器的方法来进行初始化的,其中 file_operations 这个结构体中的成员有很多,上述初始化的成员只是其中一部分,

Copy
struct file_operations {

struct module *owner;
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
int (*open) (struct inode *, struct file *);
int (*flush) (struct file *, fl_owner_t id);
int (*release) (struct inode *, struct file *);
/*还有很多,省略*/
}
AI 代码解读

采用这种指定初始化器的方法,使用灵活,而且代码易于维护。因为如果按照固定顺序赋值,当我们的 file_operations 结构体类型发生改变时,比如添加成员、减少成员、调整成员顺序,那么使用该结构体类型定义变量的大量 C 文件都需要重新调整初始化顺序,那将导致程序大幅度地更改。

结构体数组的指定初始化器#
在叙述了上面关于结构体和数组的指定初始化器之后,我们也可以以这种方式来来初始化结构体数组,比如这样:

Copy

include

int main(void)
{

struct point {int x,y;};
struct point pts[5] =
{
    [2].y = 5,
    [2].x = 6,
    [0].x = 2
};
int i;
for(i = 0;i < 5;i++)
    printf("%d %d\n",pts[i].x,pts[i].y);
AI 代码解读

}
输出结果如下:

Copy
2 0
0 0
6 5
0 0
0 0
总结
以上便是指定初始化器所包含的大致内容,这也是自己之前的知识盲点,通过这次总结学习,也能够很好的掌握了,不积跬步,无以至千里~

参考资料:
[1] https://blog.51cto.com/zhaixue/2346825
[2] https://www.geeksforgeeks.org/designated-initializers-c/
[3] https://aticleworld.com/state-machine-using-c/

作者: wenzid

出处:https://www.cnblogs.com/wenziw5/p/12792740.html

目录
打赏
0
0
0
0
47
分享
相关文章
GitLab Runner 全面解析:Kubernetes 环境下的应用
GitLab Runner 是 GitLab CI/CD 的核心组件,负责执行由 `.gitlab-ci.yml` 定义的任务。它支持多种执行方式(如 Shell、Docker、Kubernetes),可在不同环境中运行作业。本文详细介绍了 GitLab Runner 的基本概念、功能特点及使用方法,重点探讨了流水线缓存(以 Python 项目为例)和构建镜像的应用,特别是在 Kubernetes 环境中的配置与优化。通过合理配置缓存和镜像构建,能够显著提升 CI/CD 流水线的效率和可靠性,助力开发团队实现持续集成与交付的目标。
HarmonyOS Next~鸿蒙应用框架开发实战:Ability Kit与Accessibility Kit深度解析
本书深入解析HarmonyOS应用框架开发,聚焦Ability Kit与Accessibility Kit两大核心组件。Ability Kit通过FA/PA双引擎架构实现跨设备协同,支持分布式能力开发;Accessibility Kit提供无障碍服务构建方案,优化用户体验。内容涵盖设计理念、实践案例、调试优化及未来演进方向,助力开发者打造高效、包容的分布式应用,体现HarmonyOS生态价值。
64 27
深入探索 BPMN、CMMN 和 DMN:从定义到应用的全方位解析
在当今快速变化的商业环境中,对象管理组织(OMG)推出了三种强大的建模标准:BPMN(业务流程模型和符号)、CMMN(案例管理模型和符号)和DMN(决策模型和符号)。它们分别适用于结构化流程管理、动态案例处理和规则驱动的决策制定,并能相互协作,覆盖更广泛的业务场景。BPMN通过直观符号绘制固定流程;CMMN灵活管理不确定的案例;DMN以表格形式定义清晰的决策规则。三者结合可优化企业效率与灵活性。 [阅读更多](https://example.com/blog)
深入探索 BPMN、CMMN 和 DMN:从定义到应用的全方位解析
阿里云服务器ECS通用型规格族解析:实例规格、性能基准与场景化应用指南
作为ECS产品矩阵中的核心序列,通用型规格族以均衡的计算、内存、网络和存储性能著称,覆盖从基础应用到高性能计算的广泛场景。通用型规格族属于独享型云服务器,实例采用固定CPU调度模式,实例的每个CPU绑定到一个物理CPU超线程,实例间无CPU资源争抢,实例计算性能稳定且有严格的SLA保证,在性能上会更加稳定,高负载情况下也不会出现资源争夺现象。本文将深度解析阿里云ECS通用型规格族的技术架构、实例规格特性、最新价格政策及典型应用场景,为云计算选型提供参考。
可穿戴设备如何重塑医疗健康:技术解析与应用实战
可穿戴设备如何重塑医疗健康:技术解析与应用实战
44 4
DeepSeek大模型在客服系统中的应用场景解析
在数字化浪潮下,客户服务领域正经历深刻变革,AI技术成为提升服务效能与体验的关键。DeepSeek大模型凭借自然语言处理、语音交互及多模态技术,显著优化客服流程,提升用户满意度。它通过智能问答、多轮对话引导、多模态语音客服和情绪监测等功能,革新服务模式,实现高效应答与精准分析,推动人机协作,为企业和客户创造更大价值。
148 5
淘宝拍立淘按图搜索API接口系列的应用与数据解析
淘宝拍立淘按图搜索API接口是阿里巴巴旗下淘宝平台提供的一项基于图像识别技术的创新服务。以下是对该接口系列的应用与数据解析的详细分析
DeepSeek 实践应用解析:合力亿捷智能客服迈向 “真智能” 时代
DeepSeek作为人工智能领域的创新翘楚,凭借领先的技术实力,在智能客服领域掀起变革。通过全渠道智能辅助、精准对话管理、多语言交互、智能工单处理、个性化推荐、情绪分析及反馈监控等功能,大幅提升客户服务效率和质量,助力企业实现卓越升级,推动智能化服务发展。
85 1
通义灵码AI程序员实战:从零构建Python记账本应用的开发全解析
本文通过开发Python记账本应用的真实案例,展示通义灵码AI程序员2.0的代码生成能力。从需求分析到功能实现、界面升级及测试覆盖,AI程序员展现了需求转化、技术选型、测试驱动和代码可维护性等核心价值。文中详细解析了如何使用Python标准库和tkinter库实现命令行及图形化界面,并生成单元测试用例,确保应用的稳定性和可维护性。尽管AI工具显著提升开发效率,但用户仍需具备编程基础以进行调试和优化。
277 9
解锁鸿蒙装饰器:应用、原理与优势全解析
ArkTS提供了多维度的状态管理机制。在UI开发框架中,与UI相关联的数据可以在组件内使用,也可以在不同组件层级间传递,比如父子组件之间、爷孙组件之间,还可以在应用全局范围内传递或跨设备传递。
54 2

推荐镜像

更多
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等