【发布时间】:2016-03-20 19:36:22
【问题描述】:
正如标题所述,我想知道带有 flexible array member 的 C 结构数组的行为方式。这是一个例子:
struct vector {
size_t length;
double array[];
};
维基百科文章说:
此类结构上的
sizeof运算符需要给出灵活数组成员的偏移量。
在我的机器上,这对应于 8 个字节 (sizeof(size_t))。但是,当我执行以下操作时会发生什么:
显然数组不能保存向量v0 的数据,因为它只有3*8 字节= 24 字节 宽。我该如何处理这样的情况?
#define LENGTH 10
int main() {
struct vector arr[3];
struct vector *v0 = calloc(1, sizeof(*v0) + LENGTH * sizeof(v0->array[0]));
v0->length = LENGTH;
size_t i;
for (i = 0; i < v0->length; i++) {
v0->array[i] = (double) i;
}
struct vector v1;
struct vector v2;
arr[0] = *v0;
arr[1] = v1;
arr[2] = v2;
for (i = 0; i < arr[0].length; i++) {
printf("arr[0].array[%2zu] equals %2.0lf.\n", i, arr[0].array[i]);
printf(" v0->data[%2zu] equals %2.0lf.\n", i, v0->array[i]);
}
return 0;
}
例如,当我正在编写一个库(头文件:mylib.h,源代码:my lib.c)并希望对用户隐藏一个特定结构的实现(头文件中声明的结构,源代码中定义 - 隐藏)。可悲的是,这个结构包含一个灵活的数组成员。当用户尝试创建命名结构数组时,这不会导致意外行为吗?
额外:在OpenSTD C Spec 中阅读有关灵活数组的更多信息。
只需搜索“灵活数组成员”。
编辑:C11 标准的最新草案,C 语言的最新免费参考可在此处获得:http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf
【问题讨论】:
-
“当用户尝试创建命名结构数组时,这不会导致意外行为吗?”如果操作正确,则不会。如果用户不应该知道灵活数组字段,那么显而易见的事情就是让 API 为用户进行分配。
-
@kaylum 一个创建数组并且跟踪索引之类的东西的API?我的意思是索引不适用于不同大小的结构......这将如何工作?在我看来远非显而易见。
-
该结构已经有一个长度字段。这准确地告诉用户有效的索引是什么。
-
@kaylum 假设我想访问第五个元素。所以我做了类似
sizeof (struct mystruct) + array[0].length* sizeof (array[0].data[0]) + sizeof (struct mystruct) + array[1].length* sizeof (array[1].data[1]) + sizeof (struct mystruct) + array[2].length* sizeof (array[2].data[2]) + ...?我想这很好。我很确定这不是正确处理此类结构的方法。避免灵活的数组成员,做一个额外的 malloc 并使用良好的旧式数据指针成员会更有效。 -
使用
arr[i] = ...,您仅将第一个sizeof(size_t)字节复制到arr[i]。
标签: c arrays struct flexible-array-member