C语言变长嵌套数组常量初始化定义技巧

有时候,我们需要在代码里配置一些常量结构,比如一个固定的动作流程ActionFlow:包含N(即flow_num)个动作列表(ActionArray),每个动作列表包含M(即act_num)个可并行执行的动作ID。

cpp 复制代码
// 动作序列:并行执行的动作ID列表
typedef struct {
    int* p_act_arr;     // 元素指针
    int act_num;        // 元素数量
} ActionArray;

// 动作列表:按顺序执行的动作序列
typedef struct {
    ActionArray* p_flow_arr;    // 元素指针
    int flow_num;               // 元素数量
}ActionFlow;

直观看,我们希望这样配置,一目了然,但这不符合C/C++的语法规则

cpp 复制代码
// 配置固定的动作序列
ActionFlow g_act_flow = {
    {
        {{1, 2},          2},     // 第0个可并行执行的动作
        {{3, 4, 5, 6, 7}, 5},     // 第1个
        {{8},             1},     // 第2个
    },
    3                             // 共3个
};

符合规则的语法大概是这样的,看起来显得有些冗长

cpp 复制代码
static int s_act_0[] = {1, 2};
static int s_act_1[] = {3, 4, 5, 6, 7};
static int s_act_2[] = {8};
static ActionArray s_act_arr[] = {
    {s_act_0, sizeof(s_act_0)/sizeof(int)},
    {s_act_1, sizeof(s_act_1)/sizeof(int)},
    {s_act_2, sizeof(s_act_2)/sizeof(int)},
}; 
ActionFlow g_act_flow = {s_act_arr, sizeof(s_act_arr)/sizeof(ActionArray)};

为了让定义更简洁,尽可能的只提供{1,2},{3,4,5,6,7}这些我们关心的业务数据,我们可以使用C99中引入的复合字面量 (compound literals,对应C++中的列表初始化‌(list initialization))来简化上述的变长嵌套数组常量初始化定义:

cpp 复制代码
#define ARRAY(type, ...) (type[])__VA_ARGS__, sizeof((type[])__VA_ARGS__)/sizeof(type)
#define ACTARR(...) ARRAY(int, __VA_ARGS__)
#define ACTIONFLOW(name, ...) ActionFlow g_##name = {ARRAY(ActionArray, __VA_ARGS__)}
ACTIONFLOW(act_flow, {         \
    {ACTARR({1, 2})},          \
    {ACTARR({3, 4, 5, 6, 7})}, \
    {ACTARR({8})}              \
});

还有更简洁实用的方法吗?欢迎留言讨论。

相关推荐
xxxxxxllllllshi12 分钟前
Java 集合框架全解析:从数据结构到源码实战
java·开发语言·数据结构·面试
爱编程的鱼28 分钟前
Python 与 C++、C 语言的区别及选择指南
c语言·开发语言·c++
迎風吹頭髮1 小时前
UNIX下C语言编程与实践33-UNIX 僵死进程预防:wait 法、托管法、信号忽略与捕获
c语言·网络·unix
韧竹、1 小时前
详解指针2
c语言
bawangtianzun4 小时前
重链剖分 学习记录
数据结构·c++·学习·算法
ChoSeitaku8 小时前
NO.14数据结构红黑树|树高|转化4阶B树|插入操作|删除操作
数据结构·b树
T1an-18 小时前
力扣169.多数元素
数据结构·算法·leetcode
一念&9 小时前
每日一个C语言知识:C 数据类型
c语言·开发语言
小秋学嵌入式-不读研版9 小时前
C49-函数指针(通过指针调用函数)
c语言·笔记
violet-lz9 小时前
数据结构:七大线性数据结构从结构体定义到函数实现的的区别
数据结构