【问题标题】:multiple flexible array in a struct in C?C中的结构中的多个灵活数组?
【发布时间】:2013-07-09 15:33:11
【问题描述】:

我在 c 中的 s 结构中有多个灵活的数组:

typedef struct
{
   int a;
   float b;
} Name;

typedef struct
{  
   int c;
   int d;
   int e;
} NIM;

typedef struct 
{
   int age;
   int time;
   Name name[1];
   NIM  nim[1];
} EthgenSig;

如果我们需要这样分配内存:

malloc(sizeof(EthgenSig) + sizeof(Name) * 10);

内存是如何分配的,如果先操作name数组,再操作nim数组,那么nim[1]会覆盖name数组,那么如何解决呢?

【问题讨论】:

  • malloc() 只是分配所需大小的内存,不会将内存转换为任何类型。返回空指针。
  • 我不知道你想问什么......但你的代码看起来完全合适。 name 和 nim 的大小已定义,因此整个 struct EthgenSig 也是如此。
  • 您的namenim 不是灵活的数组成员;它们只是单元素数组。请参阅comp.lang.c FAQ 的问题 2.6。

标签: c arrays struct


【解决方案1】:

由于您指出的确切原因,您不能拥有多个灵活数组成员。

如果您需要将所有数据保存在同一个内存块中,最多可以创建namenim 指针并设置它们在分配后指向正确位置的位置(确保不要破坏任何对齐约束),但最简单(也是最明智)的事情是分别为 namenim 分配数组。

【讨论】:

    【解决方案2】:

    这并不难做到……关键是要意识到 C 中的数组和指针都具有非常相似的属性。实际上,数组访问器表示法与指针表示法有直接对应关系:

    a[b] == *(a + b);
    

    请注意,这具有使数组的名称和索引可互换的效果,因此这也是正确的:

    a[b] == b[a];
    

    您可以使用它来实现您想要的结果。首先,声明一个具有两个指针元素的结构。这提供了两个指针来存储两个数组的基地址:

    struct two_blocks {
        int *x;
        int *y;
    }
    

    当你分配这个结构时,你需要为两个数组的主体分配额外的空间:

    #define X_SIZE 3
    #define Y_SIZE 4
    
    two_blocks *data = (two_blocks *)malloc(sizeof(two_blocks)
                                             + (sizeof(int) * X_SIZE)
                                             + (sizeof(int) * Y_SIZE));
    

    然后最后一步就是初始化两个数组指针。 (这些表达式使用了大量的指针类型转换来确保指针运算以单个字节完成。指针运算通常以被指向对象的大小为单位完成,以支持我上面提到的数组/指针等价。 )

    data->x = (int *)(((char *)data) + sizeof(two_blocks));
    data->y = (int *)(((char *)data) + sizeof(two_blocks) + X_SIZE * sizeof(int));
    

    从那里,可以像您期望的那样使用数组:

     data->x[2] = 42;
     data->x[2] = 42;
    

    几个观察

    • 就像 Matteo 说的,小心对齐。使用这种技术会从编译器接管内存布局,这可能会导致意外问题。如果这个警告对您没有意义,那么您可能不应该使用这种技术。
    • 使用此技术的一个基本原理是,它可以通过减少您需要管理的空闲数量来简化内存管理。如果您知道您的两个数组 x 和 y 都具有与其封闭结构相同的生命周期,那么这将消除一种潜在的内存泄漏类型。 (以及通过减少内存块的数量来减少内存碎片的机会。)

    【讨论】:

      【解决方案3】:

      当涉及到这个结构的内存布局时,拥有一个大小为1 的数组与根本没有一个数组是一样的。

      你也可以这样:

      typedef struct 
      {
         int age;
         int time;
         Name name;
         NIM nim;
      } EthgenSig;
      

      但我假设这不是你想要的。很难说出你真正想要什么。但我假设你真的想要这个:

      typedef struct 
      {
         int age;
         int time;
         Name* name;
         NIM* nim;
      } EthgenSig;
      
      foo = malloc(sizeof(EthgenSig);
      foo.name = malloc(sizeof(Name)*10);
      foo.nim = malloc(sizeof(Nim) * 10);
      

      【讨论】:

        猜你喜欢
        • 2017-08-13
        • 2011-03-04
        • 1970-01-01
        • 2013-11-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多