超大C结构的分段初始化

超大C结构的分段初始化,c,struct,constants,initializing,C,Struct,Constants,Initializing,我的嵌入式应用程序存储(在ROM中,常量)非常大,非常嵌套的结构。 我正在寻找一种整洁的方法来初始化它。 因此,我们应该写: typedef struct { uint32_t n1; float fArr[5]; struct { char cArr[1000]; int32_t n3; }subStruct; // ... and on and on }Config_t; const Conf

我的嵌入式应用程序存储(在ROM中,常量)非常大,非常嵌套的结构。 我正在寻找一种整洁的方法来初始化它。 因此,我们应该写:

typedef struct {
    uint32_t    n1;
    float       fArr[5];
    struct {
        char    cArr[1000];
        int32_t n3;
    }subStruct;
    // ... and on and on 
}Config_t;

const Config_t cfg = {
    .n1 = 5,
    .fArr = {1.0, 2.0, 0, -5.6, 8.8},
    .subStruct.cArr = {1,1,1,2,2,2,3,3,3/*etc*/},
    .subStruct.n3 = 3
};
使用类似于:

const float fArrAux[5] = { 1.0, 2.0, 0, -5.6, 8.8 };
const char cArrAux[1000] = { 1,1,1,2,2,2,3,3,3/*etc*/ };

const Config_t cfg = {
    .n1 = 5,
    .fArr = fArrAux,            // ?
    .subStruct.cArr = cArrAux,  // ?
    .subStruct.n3 = 3
};
有没有一种推荐的方法可以使主结构在内存中保持连续(不包括成员填充)(它在闪存中,所以我想一次烧掉它)

此外,这种设置中的辅助定义(fArrAux、cArrAux)是否会消耗内存(从而使占用空间加倍)


感谢

注意,在C语言中,可执行代码总是出现在函数中

这两种初始化(假设它是
静态的
或全局数据,在任何函数代码之外)都是在构建时进行的,实际上是在初始化某种类型的数据

只有当
.fArr
.subStruct.cArr
是指针(而不是数组)时,您的第二个变体才有意义(应该编译)。因此,它不会编译:

e.c:18:13: error: incompatible types when initializing type ‘float’ 
                  using type ‘const float *’
     .fArr = fArrAux,            // ?
             ^~~~~~~

您可以考虑将生成过程更改为生成一些C定义,例如在一些大型生成的<代码> .c>代码>文件中,包含与第一个变体类似的东西。

注意,在C中,可执行代码总是出现在函数内。

这两种初始化(假设它是
静态的
或全局数据,在任何函数代码之外)都是在构建时进行的,实际上是在初始化某种类型的数据

只有当
.fArr
.subStruct.cArr
是指针(而不是数组)时,您的第二个变体才有意义(应该编译)。因此,它不会编译:

e.c:18:13: error: incompatible types when initializing type ‘float’ 
                  using type ‘const float *’
     .fArr = fArrAux,            // ?
             ^~~~~~~

您可以考虑将生成过程更改为生成一些C定义,例如在一些大型生成的<代码> .c>代码>文件中,包含与第一个变体相似的东西。

如果您只想在视觉上分离长数组初始化器,可以考虑将它们定义为宏:

#define CFG_FARR             { 1.0, 2.0, 0, -5.6, 8.8 }
#define CFG_SUBSTRUCT_CARR   { 1, 1, 1, 2, 2, 2, 3, 3, 3, /*etc*/ }

const Config_t cfg = {
    .n1 = 5,
    .fArr = CFG_FARR,
    .subStruct.cArr = CFG_SUBSTRUCT_CARR,
    .subStruct.n3 = 3
};

如果您只想在视觉上分离长数组初始化器,可以考虑将它们定义为宏:

#define CFG_FARR             { 1.0, 2.0, 0, -5.6, 8.8 }
#define CFG_SUBSTRUCT_CARR   { 1, 1, 1, 2, 2, 2, 3, 3, 3, /*etc*/ }

const Config_t cfg = {
    .n1 = 5,
    .fArr = CFG_FARR,
    .subStruct.cArr = CFG_SUBSTRUCT_CARR,
    .subStruct.n3 = 3
};

您可以将实际数据保存在一个文件中,您可以使用某种外部工具生成或创建该文件,该工具还允许您在将数据作为初始值分配给结构和数组之前检查数据的正确性:


免责声明:我没有测试这个。在其他情况下,我为我编写了一个小程序。

您可以将实际数据保存在一个文件中,您可以使用一些外部工具生成或创建该文件,这也可以让您在将数据作为初始值分配给结构和数组之前检查数据的正确性:


免责声明:我没有测试这个。在其他情况下,我为自己编写了一个小程序。

为什么您觉得第二种方法比第一种更整洁?此外,这个问题似乎有两个问题:1)关于初始化,2)关于避免填充,“这种设置中的辅助定义(fArrAux,cArrAux)会消耗内存吗”可能是的。第一个变体更干净;它明确地初始化了您想要初始化的内容,并且明显地不会产生任何意外开销的风险。第二个无论如何都不起作用——至少,不像书面的那样——这是选择第一个的另一个原因;这个问题是基于主要观点的;为什么你觉得第二种方法比第一种更整洁?此外,这个问题似乎有两个问题:1)关于初始化,2)关于避免填充,“这种设置中的辅助定义(fArrAux,cArrAux)会消耗内存吗”可能是的。第一个变体更干净;它明确地初始化了您想要初始化的内容,并且明显地不会产生任何意外开销的风险。第二个无论如何都不起作用——至少,不像书面的那样——这是选择第一个的另一个原因;这个问题是基于主要观点的;