c - 声明复杂 C 结构化常量数据的策略?

标签 c embedded c99 literals compound-literals

我有一个复杂的数据结构(有很多不完整的数组类型/异构长度的结构数组和指向结构数组的结构指针......)

我想把它们放在闪存中,所以我考虑将它们放在静态存储的 const 对象中(它们将存储在闪存中),让编译器完成它的工作。

我在嵌入式环境中工作,其中 ROM==flash==data 我无法进行物理更改。我的 RAM 很少,当然也不足以存储我所有的数据。可以告诉 GCC 毫无问题地将静态常量数据存储到 ROM。

数据不能动态构造,因为它应该保留在闪存中。

我目前正在使用 C(不是 C++)和 4.8 gcc,并且不介意使用 GCCisms。

但是我不断遇到错误消息,例如:

  • 初始化元素不是常量
  • 不兼容的指针类型
  • ...

与最近的不同 gcc 版本不同,表明此功能(混合复合文字、指定的初始化器、...)是最近的或不是主线。

请注意,此代码是由程序(脚本)生成的。

除了我不断犯的错误(我可以更具体并在那里寻求帮助),你会建议什么策略:

  • 继续尝试使用复合文字来使用复杂的嵌套文字结构
    • 具有大量类型的复合文字
    • 具有多个相互指向的复合文字类型
  • 用他们的名字构建许多中间对象(使整个事情变得非常不可读)
  • 构建一个大的 uint32_t datablob[] 并适本地转换我的结构(额外的是无法在对象之间存储指针,因为我的链接器将指定这将在何处结束)

  • 还有其他选择吗?

(编辑:添加细节)

好吧,我的问题更多是关于通用策略,但这里有一个例子:

struct A
{
    int id; 
    int codes[]; 
};

struct B 
{
    int b_member;
    struct A *a[]; // array of ptr to A objects
};


struct C 
{
    int c_member;
    struct B *objects[]; // array of ptrs on B
};

const struct A rom_data = { .id=4, .codes = {1,2,3,4}}; // this is in ROM

int main(void) {}

我想像为 A 所做的那样声明一个 C 结构数组。 (这意味着我不想复制数据、从磁盘读取数据或对其进行 malloc,只需声明一个包含数据的 const。)

我所有关于文字的例子都非常简单。

我的平台的细节是一个 ARM 微 Controller ,但考虑到我想声明一个 const。

最佳答案

您应该使用 const 限定的指针而不是灵活的数组成员。

有一些示例代码:

#include <stddef.h>

struct A
{
    int id; 
    const int *codes; 
};

struct B 
{
    int b_member;
    const struct A *const *a;
};

struct C 
{
    int c_member;
    const struct B *const *objects;
};

static const struct C ROOT = { 0, (const struct B *[]){
    &(const struct B){ 0, (const struct A *[]){
        &(const struct A){ 0, (const int []){ 1, 2, 3 } },
        &(const struct A){ 1, (const int []){ 0 } },
    } },
    &(const struct B){ 42, NULL },
} };

如评论中所述,似乎没有必要通过指针引用结构。这简化了代码:

#include <stddef.h>

struct A
{
    int id; 
    const int *codes; 
};

struct B 
{
    int b_member;
    const struct A *a;
};

struct C 
{
    int c_member;
    const struct B *objects;
};

static const struct C ROOT = { 0, (const struct B []){
    { 0, (const struct A []){
        { 0, (const int []){ 1, 2, 3 } },
        { 1, (const int []){ 0 } },
    } },
    { 42, NULL },
} };

如果您想要或需要 C90 兼容性,您可以展平树并让生成脚本跟踪相应数组中的偏移量:

static const int ARRAY_OF_INT[] = {
    1, 2, 3,
    0,
};

static const struct A ARRAY_OF_A[] = {
    { 0, ARRAY_OF_INT + 0 },
    { 1, ARRAY_OF_INT + 3 },
};

static const struct B ARRAY_OF_B[] = {
    { 0, ARRAY_OF_A + 0 },
    { 42, NULL },
};

static const struct C ROOT = { 0, ARRAY_OF_B + 0 };

关于c - 声明复杂 C 结构化常量数据的策略?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25652918/

相关文章:

arm - IAR Embedded Workbench 菜单栏缺失

c++ - 指针转换字节顺序

c - 在 C99 中的 for 循环体之外声明计数器有什么好处吗?

c - 学习使用内在函数——使用 _mm256_sub_ps 的段错误

assembly - 自动检测违反程序集调用约定的情况

c - 在 Windows XP 上 system() 调用返回 "Permission Denied"

c - 使用指向第一个参数的指针迭代函数的参数

c - 如何获得复杂的 C 预处理器行为以简化动态程序汇编

c - 我怎么知道不确定类型参数的大小

c - C语言文件读写