我在程序中实现了一个文件结构,但对于结构中的某些数组,我不知道它的大小。数组的大小存储在另一个变量中,但在填充结构之前它是未知的。
struct Vertex {
float x;
float y;
float z;
};
struct myFile {
ulong nVertices;
Vertex vertices[nVertices];
};
出现错误:“错误C2065:'nVertices':未声明的标识符”。
答案 0 :(得分:14)
您应该在结构中存储指针:
Vertex *vertices;
然后在运行时分配内存:
myFile f;
f.vertices = malloc(nVertices * sizeof(Vertex));
if (f.vertices == 0)
handle_out_of_memory();
f.nVertices = nVertices;
完成后请记得释放内存:
free(f.vertices);
答案 1 :(得分:10)
C99引入了“灵活的阵列成员”,这可能是您想要使用的。您的代码最终看起来非常像@frast建议的代码,但略有不同。
§6.7.2.1结构和联合说明符
结构或联合不得包含不完整或功能类型的成员(因此, 结构不应包含自身的实例,但可以包含指向实例的指针 它本身),除了具有多个命名成员的结构的最后一个成员 可能有不完整的数组类型;这样的结构(和任何包含的结合,可能 递归地,这种结构的成员不应该是结构的成员或者 数组的元素。
[...]
作为一种特殊情况,具有多个命名成员的结构的最后一个元素可以 有一个不完整的数组类型;这被称为灵活的阵列成员。有两个 异常,灵活的数组成员被忽略。首先,结构的大小应为 等于替换其他相同结构的最后一个元素的偏移量 具有未指定长度数组的灵活数组成员。 106)其次,当a。 (或 - >) operator有一个左操作数,它是一个带有灵活数组成员的结构(指向) 并且右边的操作数命名该成员,它的行为就像该成员被替换一样 最长的数组(具有相同的元素类型),不会构成结构 大于被访问的对象;数组的偏移量应保持为 灵活的阵列成员,即使这与替换阵列的成员不同。如果这 数组没有元素,它的行为好像它有一个元素,但行为是 如果尝试访问该元素或生成过去的指针,则为undefined 它
示例假设所有数组成员在声明之后对齐相同:
struct s { int n; double d[]; }; struct ss { int n; double d[1]; };
三个表达式:
sizeof (struct s) offsetof(struct s, d) offsetof(struct ss, d)
具有相同的值。结构struct具有灵活的数组成员d。
如果sizeof(double)为8,则在执行以下代码后:
struct s *s1; struct s *s2; s1 = malloc(sizeof (struct s) + 64); s2 = malloc(sizeof (struct s) + 46);
并假设对malloc的调用成功,s1和s2指向的对象的行为就像是 标识符已声明为:
struct { int n; double d[8]; } *s1; struct { int n; double d[5]; } *s2;
进一步成功完成作业后:
然后他们表现得好像声明是:s1 = malloc(sizeof (struct s) + 10); s2 = malloc(sizeof (struct s) + 6);
struct { int n; double d[1]; } *s1, *s2;
和
double *dp; dp = &(s1->d[0]); // valid *dp = 42; // valid dp = &(s2->d[0]); // valid *dp = 42; // undefined behavior
作业:
*s1 = *s2;
仅复制成员n而不复制任何数组元素。类似地:
struct s t1 = { 0 }; // valid struct s t2 = { 2 }; // valid struct ss tt = { 1, { 4.2 }}; // valid struct s t3 = { 1, { 4.2 }}; // invalid: there is nothing for the 4.2 to initialize t1.n = 4; // valid t1.d[0] = 4.2; // undefined behavior
106)未指定长度以允许实现可能使数组成员不同 根据它们的长度进行对齐。
该示例来自C99标准。