在C中动态分配结构和数组

时间:2011-12-16 20:31:30

标签: c arrays memory dynamic structure

  1. 如何动态分配struct Register数组,每个寄存器的动态分配数组为struct Field
  2. 我将如何访问这些成员(我可以使用Register_A.FieldArray[23].High吗?)?
  3. 如何有效地初始化寄存器结构(假设寄存器结构数组很大)? (就像没有花费任何计算的数据段一样)

    struct Field
    {
        char    High;                
        char    Low;                
        char    Attribute;
    };
    
    struct Register 
    {
       unsigned int    ResetValue;
       struct Field    FieldArray[];
    };
    

4 个答案:

答案 0 :(得分:3)

我强烈反对你不使用弹性阵列,因为它们只不过是一块硬币。您应该声明并将其用作struct Field *malloc将其设置为与任何其他动态数组一样大小。

那就是malloc,数组大小为n_elem

struct Register register = malloc(sizeof(*register) + n_elem * sizeof(*register->FieldArray));

访问元素:

char high = register->FieldArray[0].High;

对于初始化:in gcc, at least,,您可以像任何其他静态数组一样静态初始化数组部分。我不确定其他编译器如何处理它。


为什么不鼓励使用flex数组:

我会链接this post,但我不认为答案是完整的(大多数沮丧是因为它只是c-99),所以我会添加我的想法。
他们是个例外。从本质上讲,您声明数组的大小为零,并且每次都在界限范围内访问它,只是在您分配的范围内。您不能像任何其他结构一样使用具有灵活数组的结构,例如你不能把sizeof灵活的数组拿走。如果声明一个静态的或一个数组,则不能使用该数组成员,因为没有为它分配空间。

在数组中使用它们的示例:

#include <stdio.h>

struct test {
        int val;
        int arr[];
};

int main() {
        struct test tarr[2];
        printf("%p\n%p\n", &tarr[0].arr[0], &tarr[1].val);
}

输出:

0x7fff59b67164
0x7fff59b67164

他们在同一个地址。如果尝试写入数组成员,则会覆盖下一个对象。如果您尝试从中读取,则从下一个对象读取数据。根据填充,这甚至可能是填充的无意义值。

它们就像goto语句一样,两者都有用,但往往是个坏主意。如果您不知道为什么它们是危险的,您就不应该使用它们(在实际代码中;在测试程序中使用它们以了解如何正确使用它们以及它们如何引入它们并不是一个坏主意问题)。

答案 1 :(得分:1)

一种方法是改变struct Register

的大小
struct Register 
{
   unsigned int    ResetValue;
   struct Field    FieldArray[1];
};
struct Register *Register_Create()
{
    struct Register *reg = calloc(1, sizeof(struct Register) - sizeof(struct Field));
    // check for NULL pointer
    return reg;
}

struct Register *Register_SetSize(struct Register *reg, size_t size)
{
    // check for NULL
    reg = realloc(reg, sizeof(struct Register) + sizeof(struct Field) * (size - 1));
    // check for NULL
    return reg;
}

以下是如何使用它的示例:

struct Register *reg = Register_Create();
reg = Register_SetSize(register, 5);
// You now have space for 5 elements in reg->FieldArray
reg->FieldArray[3].High = 'B';

请注意,只有在FieldArray末尾放置struct时,此解决方案才有效。

答案 2 :(得分:0)

你必须知道FieldArray有多大。如果未修复,则需要声明最大值。然后您可以按照指定的方式分配注册和访问

答案 3 :(得分:0)

灵活阵列成员是C99的一部分。

  1. 您可以按照自己的想法分配struc灵活数组成员:malloc(sizeof(struct Register) + sizeof(struct Field[n])),其中n是您想要的大小。不要忘记初始化数组并跟踪n,最好通过将成员专门用于此目的
  2. 顺便说一句:上面的malloc可能由于填充而浪费了一些字节,但通常不值得考虑确切的公式。最小的一个有最大值并使用offsetof