是否可以在C中使用嵌套的灵活数组(flexible array of flexible arrays)?
我尝试了以下代码来测试灵活数组:
#include <stdlib.h>
#include <stdio.h>
typedef struct {
int x;
int y;
} node;
typedef struct {
int len;
node elem[];
} cell;
int cell_size = 3;
int main(void) {
cell *set = malloc(sizeof *set + cell_size * sizeof set->elem[0]);
set->len = cell_size;
for (int j = 0; j < cell_size; j++) {
set->elem[j].x = j;
set->elem[j].y = j * 10;
}
printf("set size: %d\n", set->len);
for (int j = 0; j < cell_size; j++) {
printf("x: %d, ", set->elem[j].x);
printf("y: %d\n", set->elem[j].y);
}
return 0;
}
输出为:
set size: 3
x: 0, y: 0
x: 1, y: 10
x: 2, y: 20
这里一切都按预期进行。 set
的已分配空间为 28 个字节。
但是当我尝试修改此代码以将灵活数组放入其他数组中时:
#include <stdlib.h>
#include <stdio.h>
typedef struct {
int x;
int y;
} node;
typedef struct {
int len;
node elem[];
} cell;
typedef struct {
int len;
cell group[];
} obj;
int cell_size = 3;
int obj_size = 4;
int main(void) {
obj *set = malloc(
sizeof *set + obj_size * sizeof (
sizeof (cell) + cell_size * sizeof(node)
));
set->len = obj_size;
for (int i = 0; i < obj_size; i++) {
set->group[i].len = cell_size;
for (int j = 0; j < cell_size; j++) {
set->group[i].elem[j].x = j;
set->group[i].elem[j].y = j * 10 + i;
}
}
printf("set size: %d\n", set->len);
for (int i = 0; i < obj_size; i++) {
printf("group size: %d\n", set->group[i].len);
for (int j = 0; j < cell_size; j++) {
printf("x: %d, ", set->group[i].elem[j].x);
printf("y: %d\n", set->group[i].elem[j].y);
}
}
return 0;
}
set
的分配空间为 20 个字节,并且输出错误:
set size: 4
group size: 3
x: 3, y: 3
x: 3, y: 0
x: 3, y: 1
group size: 3
x: 3, y: 3
x: 0, y: 3
x: 1, y: 13
group size: 3
x: 3, y: 0
x: 3, y: 1
x: 13, y: 2
group size: 3
x: 0, y: 3
x: 1, y: 13
x: 2, y: 23
即使我手动将malloc
设置为任何合理的值,输出仍然不正确。我认为这是因为编译器不知道顶部结构(group[]
)中obj
成员的大小。但是我没有收到任何编译器错误或警告(GCC 6.3.0)。
我不知道如何设置此大小并使编译器正确处理此代码。
答案 0 :(得分:2)
正确的...无法制作“嵌套的灵活数组”。
数组的所有成员必须具有相同的大小。你必须有
sizeof arr[i] == sizeof arr[j]
对于数组边界内的所有i
,j
。
答案 1 :(得分:2)
具有灵活数组成员的结构不能用作其他结构或数组中的成员。您只能拥有一个FAM。否则,如果您尝试声明FAM数组,则该结构数组的每个FAM成员都将指向相邻数组成员之间的内存位置-这样您将看到不正确的覆盖结果。
有关适用的C标准部分的完整讨论,请参见:How does an array of structures with flexible array members behave?
"So, there is no way to make nested flexible arrays working?"
回答:否
那会违反C11 Standard - 6.7.2.1 Structure and union specifiers(p3)
"Something similar?"
答案:是
您所需要做的就是制作node elem[];
node *elem;
,然后为每个cell_size * sizeof (node)
分配set->group[i].elem
个字节,例如
typedef struct {
int len;
node *elem;
} cell;
...
obj *set = malloc (sizeof *set + obj_size * sizeof (cell));
...
for (int i = 0; i < obj_size; i++) {
set->group[i].len = cell_size;
set->group[i].elem = malloc (cell_size * sizeof (node));
这将为每个cell_size * sizeof (node)
做您想做的事,例如{p>
set->group[i].elem
使用/输出示例
#include <stdlib.h>
#include <stdio.h>
typedef struct {
int x;
int y;
} node;
typedef struct {
int len;
node *elem;
} cell;
typedef struct {
int len;
cell group[];
} obj;
int cell_size = 3;
int obj_size = 4;
int main (void) {
obj *set = malloc (sizeof *set + obj_size * sizeof (cell));
set->len = obj_size;
for (int i = 0; i < obj_size; i++) {
set->group[i].len = cell_size;
set->group[i].elem = malloc (cell_size * sizeof (node));
for (int j = 0; j < cell_size; j++) {
set->group[i].elem[j].x = j;
set->group[i].elem[j].y = j * 10 + i;
}
}
printf("set size: %d\n", set->len);
for (int i = 0; i < obj_size; i++) {
printf("group size: %d\n", set->group[i].len);
for (int j = 0; j < cell_size; j++) {
printf("x: %d, ", set->group[i].elem[j].x);
printf("y: %d\n", set->group[i].elem[j].y);
}
free (set->group[i].elem);
}
free (set);
return 0;
}
内存使用/错误检查
$ ./bin/fam_array2
set size: 4
group size: 3
x: 0, y: 0
x: 1, y: 10
x: 2, y: 20
group size: 3
x: 0, y: 1
x: 1, y: 11
x: 2, y: 21
group size: 3
x: 0, y: 2
x: 1, y: 12
x: 2, y: 22
group size: 3
x: 0, y: 3
x: 1, y: 13
x: 2, y: 23
仔细检查一下,如果还有其他问题,请告诉我。
答案 2 :(得分:1)
您不能拥有其大小在编译时未知的对象的灵活数组。并且具有柔性阵列构件的结构的尺寸没有。唯一已知的是没有柔性构件的尺寸。
但是在您的用例中,所有 flexible 数组都将具有相同的大小,即使只有在运行时才知道。因此,您可以用指针替换内部结构的弹性数组,为结构分配足够的空间(包括其弹性数组),并为所有节点分配足够的空间,然后在该可用空间中分配指针。代码可能是:
#include <stdlib.h>
#include <stdio.h>
typedef struct {
int x;
int y;
} node;
typedef struct {
int len;
node *elem;
} cell;
typedef struct {
int len;
cell group[];
} obj;
int cell_size = 3;
int obj_size = 4;
int main(void) {
obj *set = malloc(
sizeof *set + obj_size * (
sizeof(cell) + cell_size * sizeof(node)
));
set->len = obj_size;
// nodes will exist in the allocated buffer after the cells
node *node_start = (node *)(((char *) set) + sizeof *set + obj_size * sizeof(cell));
for (int i = 0; i < obj_size; i++) {
set->group[i].len = cell_size;
// assign the elem pointers in the free space
set->group[i].elem = node_start + i * cell_size;
for (int j = 0; j < cell_size; j++) {
set->group[i].elem[j].x = j;
set->group[i].elem[j].y = j * 10 + i;
}
}
printf("set size: %d\n", set->len);
for (int i = 0; i < obj_size; i++) {
printf("group size: %d\n", set->group[i].len);
for (int j = 0; j < cell_size; j++) {
printf("x: %d, ", set->group[i].elem[j].x);
printf("y: %d\n", set->group[i].elem[j].y);
}
}
free(set);
return 0;
}