在struct中作为数组大小变量

Mid*_*das 9 c arrays data-structures

我在我的程序中实现了一个文件的结构,但对于结构中的一些数组,我不知道它的大小.数组的大小存储在另一个变量中,但在填充结构之前它是未知的.

struct Vertex {
    float x;
    float y;
    float z;
};
struct myFile {
    ulong nVertices;
    Vertex vertices[nVertices];
};
Run Code Online (Sandbox Code Playgroud)

这给出了一个错误:"错误C2065:'nVertices':未声明的标识符".

fra*_*ast 14

您应该在结构中存储指针:

Vertex *vertices;
Run Code Online (Sandbox Code Playgroud)

然后在运行时分配内存:

myFile f;
f.vertices = malloc(nVertices * sizeof(Vertex));
if (f.vertices == 0)
    handle_out_of_memory();

f.nVertices = nVertices;
Run Code Online (Sandbox Code Playgroud)

记得完成后释放内存:

free(f.vertices);
Run Code Online (Sandbox Code Playgroud)

  • 并记住在使用指针之前检查分配是否有效. (4认同)

Jon*_*ler 10

C99引入了"灵活的阵列成员",这可能是您想要使用的.你的代码最终看起来非常像@frast建议的代码,但却略有不同.

§6.7.2.1结构和联合说明符

结构或联合不应包含具有不完整或函数类型的成员(因此,结构不应包含其自身的实例,但可以包含指向其自身实例的指针),除了结构的最后一个成员具有多个一个命名成员可能有不完整的数组类型; 这样的结构(以及可能递归地包含这种结构的成员的任何联合)不应是结构的成员或数组的元素.

[...]

作为一种特殊情况,具有多个命名成员的结构的最后一个元素可能具有不完整的数组类型; 这被称为灵活的阵列成员.除了两个例外,灵活的数组成员将被忽略.首先,结构的大小应等于其他相同结构的最后一个元素的偏移量,该结构用一个未指定长度的数组替换柔性阵列成员.106)第二,当一个.(或 - >)运算符有一个左操作数,它是一个带有灵活数组成员的结构(一个指针),右操作数命名该成员,它的行为就好像该成员被最长的数组替换(具有相同的元素类型) )不会使结构大于被访问的对象; 数组的偏移量应保持为灵活数组成员的偏移量,即使这与替换数组的偏移量不同.如果此数组没有元素,则其行为就好像它有一个元素,但如果尝试访问该元素或生成一个超过它的指针,则行为是未定义的.

示例假设所有数组成员在声明后对齐相同:

struct s { int n; double d[]; };
struct ss { int n; double d[1]; };
Run Code Online (Sandbox Code Playgroud)

三个表达式:

sizeof (struct s)
offsetof(struct s, d)
offsetof(struct ss, d)
Run Code Online (Sandbox Code Playgroud)

具有相同的价值.结构struct具有灵活的阵列成员d.

如果sizeof(double)为8,则在执行以下代码之后:

struct s *s1;
struct s *s2;
s1 = malloc(sizeof (struct s) + 64);
s2 = malloc(sizeof (struct s) + 46);
Run Code Online (Sandbox Code Playgroud)

假设对malloc的调用成功,s1和s2指向的对象就像标识符声明为:

struct { int n; double d[8]; } *s1;
struct { int n; double d[5]; } *s2;
Run Code Online (Sandbox Code Playgroud)

进一步成功完成任务后:

s1 = malloc(sizeof (struct s) + 10);
s2 = malloc(sizeof (struct s) + 6);
Run Code Online (Sandbox Code Playgroud)

然后他们表现得好像声明是:

struct { int n; double d[1]; } *s1, *s2;
Run Code Online (Sandbox Code Playgroud)

和:

double *dp;
dp = &(s1->d[0]); // valid
*dp = 42; // valid
dp = &(s2->d[0]); // valid
*dp = 42; // undefined behavior
Run Code Online (Sandbox Code Playgroud)

分配:

*s1 = *s2;
Run Code Online (Sandbox Code Playgroud)

仅复制成员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
Run Code Online (Sandbox Code Playgroud)

106)未指定长度以允许实现可以根据阵列成员的长度给予阵列成员不同的对齐.

该示例来自C99标准.