0

我有以下代码:

typedef struct
{
   int name;
   int info[1]; 
} Data;

然后我有五个变量:

int a, b, c, d, e;

如何将其用作灵活数组来保留五个变量的所有值?

4

3 回答 3

7

要正确执行此操作,您应该将灵活数组成员声明为不完整类型:

typedef struct
{
   int name;
   int info[]; 
} Data;

然后为它动态分配内存

Data* data = malloc(sizeof(Data) + sizeof(int[N]));

for(int i=0; i<N; i++)
{
  data->info[i] = something; // now use it just as any other array
}

编辑

确保您使用的是 C99 编译器,否则您将遇到各种问题:

如果你分配一个长度为 1 的数组,那么你将 malloc 1 项用于数组的第一个元素和结构,然后在之后追加N字节。这意味着您实际上是在分配N+1字节。这可能不是一个人打算做的,它使事情变得不必要地复杂。

(为了解决上述问题,GCC 有一个 C99 之前的扩展,它允许零长度数组,这在标准 C 中是不允许的。)

在 C99 之前,或者在任何其他上下文中,除了作为灵活的数组成员之外,C 不允许像我的代码中所示的那样不完整的数组类型。

C99 保证您的程序在使用灵活的数组成员时是良好定义的。如果您不使用 C99,那么编译器可能会在最后的其他结构成员和数组之间附加“结构填充”字节。这意味着它data->info[0]可能指向结构填充字节,而不是分配数组中的第一项。这可能会导致各种奇怪的、意外的行为。

这就是为什么在 C99 之前灵活的数组成员被称为“struct hack”的原因。他们不可靠,只是一个肮脏的黑客可能会或可能不会工作。

于 2013-06-27T13:54:11.870 回答
2

这种结构在 C 语言中是一个比较常见的习惯用法。这个想法是您在 的末尾分配额外的空间struct,其中第一个info之后的元素实际存储在其中。then末尾的 size-1 数组成员struct允许您使用数组语法来访问此数据。

如果你想存储 5 个元素,你必须这样做:

Data * data=malloc(sizeof(Data)+sizeof(int)*4); /* 4 because the first element is
                                                already included in the size of
                                                the struct */
/* error checking omitted ... */
data->info[0]=a;
data->info[1]=b;
data->info[2]=c;
data->info[3]=d;
data->info[4]=e;
/* ... */
/* when you don't need d anymore remember to deallocate */
free(data);

您还可以编写一个辅助函数来简化分配:

Data * AllocateData(size_t elements)
{
    if(elements==0)
        return NULL;
    return malloc(sizeof(Data)+sizeof(int)*(elements-1));
}

上面的例子是

Data * data=AllocateData(5);
/* then as above */
于 2013-06-27T13:48:19.550 回答
2

这称为灵活数组,是在 C99 中引入的。通常也称为struct hack。在 C99 中,应声明灵活数组成员而不指定大小。

您需要动态分配可以容纳比结构大小更多的内存的内存。由于数组是结构中的最后一个成员,因此只要为它分配了足够的内存,就可以将其索引超过其大小。

    typedef struct
    {
       int name;
       int info[1]; 
    } Data;

Data *d = malloc(sizeof(*d) + (5 * sizeof(int)); //enough for the struct and 5 more ints.
//we have enough room for 6 elements in the info array now
//since the struct has room for 1 element, and we allocated room for another 5 ints
d->info[0] = 1;
d->info[1] = 2;
d->info[2] = 3;
d->info[3] = 4;
d->info[4] = 5;
d->info[5] = 6; 

int info[1];以这种方式使用大小为 1 的数组成员在技术上是未定义的行为 - 但在许多流行的编译器上都可以正常工作。对于 C99 编译器,这是由声明为int info[];. 在这里阅读更多

于 2013-06-27T13:49:24.840 回答