灵活的阵列成员真的有必要吗?

时间:2013-08-01 18:25:04

标签: c struct flexible-array-member

显然,具有灵活数组成员的结构不是要声明的,而是与指向该结构的指针一起使用。声明灵活的数组成员时,必须至少有一个其他成员,并且灵活数组成员必须是该结构中的最后一个成员。

假设我有一个看起来像这样的人:

struct example{
    int n;
    int flm[]; 
}

然后要使用它,我将必须声明一个指针并使用malloc为结构的内容保留内存。

struct example *ptr = malloc(sizeof(struct example) + 5*sizeof(int)); 

也就是说,如果我希望我的flm []数组保持五个整数。然后,我可以使用我的结构 像这样:

ptr->flm[0] = 1; 

我的问题是,我不应该只使用指针代替吗?它不仅在C99之前兼容,而且我可以在有或没有指向该结构的指针的情况下使用它。 考虑到我已经必须将malloc与flm一起使用,我不应该只能这样做吗?

考虑示例结构的这个新定义;

struct example{
    int n; 
    int *notflm; 
}

struct example test = {4, malloc(sizeof(int) * 5)}; 

我甚至能够以与柔性阵列成员相同的方式使用替换:

这也有效吗? (假设上面的示例定义为notflm)

struct example test; 
test.n = 4; 
notflm = malloc(sizeof(int) * 5); 

2 个答案:

答案 0 :(得分:25)

指针不是数组。选择使用哪个的基本原因与数组与指针一样。在灵活数组成员的特殊情况下,以下是您可能更喜欢它们而不是指针的一些原因:

  • 降低存储要求。指针将通过(通常)4或8个字节扩大您的结构,如果您单独分配指向存储而不是单次调用malloc,您将在开销上花费更多。

  • 提高访问效率。柔性阵列构件位于与结构基座恒定的偏移处。指针需要单独的解引用。这会影响访问它所需的指令数量和注册压力。

  • 分配成功/失败的原子性。如果您分配结构并为其分配存储以指向两个单独的步骤,那么在故障情况下清理代码将会更加丑陋,因为您遇到了一个成功而另一个成功的情况。这可以通过一些指针算法来避免同样的malloc请求,但是由于对齐问题很容易导致逻辑错误并调用UB。

  • 避免需要深层复制。如果你使用一个灵活的数组而不是一个指针,你可以简单地memcpy(不分配,因为赋值不能知道灵活的数组长度)来复制结构,而不是必须复制指向的数据并修复指针在新副本中。

  • 避免深度自由的需要。能够仅free单个对象而不是free指向数据也非常方便和干净。当然,这也可以通过上面提到的“单一malloc”方法来实现,但灵活的数组使其更容易且更不容易出错。

  • 当然还有更多原因......

答案 1 :(得分:0)

这些概念绝对没有必要,因为你已经指出了自己。

您所演示的两者之间的差异在于您的数据位于内存中。

在第一个使用灵活数组的示例中,元数据和数组本身位于同一个内存块中,如果必须,可以作为一个块(指针)移动。

在第二个示例中,您的元数据位于堆栈上,而您的数组位于堆上的其他位置。为了移动/复制它,您现在需要移动两块内存并更新元数据结构中的指针。

通常,当您需要将数组及其元数据在空间中放在内存中时,会使用灵活大小的数组。

这是绝对有用的一个例子,例如当一个数组放入一个文件中的元数据时 - 你只有一个连续的内存块,每次加载它时(很可能)放在不同的位置您的VM。

相关问题