【问题标题】:Piece-wise initialization of very large C struct非常大的 C 结构的分段初始化
【发布时间】:2018-01-01 11:07:32
【问题描述】:

我的嵌入式应用程序存储(在 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)是否会消耗内存(因此占用空间增加一倍)?

谢谢

【问题讨论】:

  • 为什么你觉得第二种方法比第一种更整洁?此外,这个问题似乎是两个问题:1.)关于初始化和 2.)关于避免填充
  • "这样的设置中的辅助定义(fArrAux, cArrAux)会不会消耗内存" 可能是的。
  • 第一个变种更干净;它清楚地初始化了您要初始化的内容,并且显然不会冒任何意外开销的风险。无论如何,第二个不起作用——至少,不像写的那样——这是更喜欢第一个的另一个原因。
  • 我将使用第一个的变体,但您的示例不能反映您的真实情况;此问题基于主要意见;

标签: c struct constants initializing


【解决方案1】:

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

#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
};

【讨论】:

    【解决方案2】:

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

    这两种初始化(假设它是static 或全局数据,在任何函数代码之外)都在构建时发生,实际上是在初始化某种code segment

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

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

    您可以考虑将构建过程更改为例如生成一些 C 定义,例如在一些大型生成的.c 文件中包含类似于第一个变体的内容。

    【讨论】:

      【解决方案3】:

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

      const Config_t cfg = {
          .n1 = 5,
          .fArr = 
      #include "fArrData.txt"
          ,
          .subStruct.cArr = 
      #include "cArrData.txt"
          ,
          .subStruct.n3 = 3
      };
      

      免责声明:我没有对此进行测试。在其他情况下,我编写了一个小程序来为我执行此操作。

      【讨论】:

        猜你喜欢
        • 2016-09-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-03-27
        • 2018-10-18
        • 2012-07-16
        相关资源
        最近更新 更多