如何正确使用灵活数组成员?

Bob*_*nis 2 c unions flexible-array-member

这是我声明的类型:(
我也t_sphere声明了)t_cylindert_triangle

typedef struct  s_intersection{
  double       t1;
  double       t2;
  int id;
  union {
    t_sphere sph;
    t_cylinder cyl;
    t_triangle tri;
  } u[];
} t_intersection;
Run Code Online (Sandbox Code Playgroud)

要引用结构体中的联合变量,我必须提前知道它是什么类型。这是可能的,这要归功于我的结构中声明的 id int,但是用我想到的方法来实现它是非常繁重的。
这是我编写的用于分配 t_intersection 变量的函数:

t_intersection  *intersection(unsigned int geometric_figure_id, void *figure)
{
    t_intersection  *p;

    if (geometric_figure_id == SPHERE_ID)
        p = malloc(sizeof(*p) + sizeof (p->u[0].sp));
    else if (geometric_figure_id == CYLINDER_ID)
        p = malloc(sizeof(*p) + sizeof (p->u[0].cy));
    else if (geometric_figure_id == TRIANGLE_ID)
        p = malloc(sizeof(*p) + sizeof (p->u[0].tr));
    if (p == NULL)
        return (NULL);
    memset(&p, 0, sizeof(p));
    p->id = geometric_figure_id:
    if (geometric_figure_id == SPHERE_ID)
        p->u[0].sp = *(t_sphere *)figure;
    else if (geometric_figure_id == CYLINDER_ID)
        p->u[0].cy = *(t_cylinder *)figure;
    else if (geometric_figure_id == TRIANGLE_ID)
        p->u[0].tr = *(t_triangle *)figure;
    return (p);
}
Run Code Online (Sandbox Code Playgroud)

有更好的方法来实现这一目标吗?
编辑:我添加了我忘记的 malloc + 分配了 id...

dbu*_*ush 5

您需要始终为整个联盟分配空间,而不仅仅是一个成员。此外,您还可以用来calloc分配零初始化的内存。

所以你可以替换这个:

if (geometric_figure_id == SPHERE_ID)
    p = malloc(sizeof(*p) + sizeof (p->u[0].sp));
else if (geometric_figure_id == CYLINDER_ID)
    p = malloc(sizeof(*p) + sizeof (p->u[0].cy));
else if (geometric_figure_id == TRIANGLE_ID)
    p = malloc(sizeof(*p) + sizeof (p->u[0].tr));
if (p == NULL)
    return (NULL);
memset(&p, 0, sizeof(p));
Run Code Online (Sandbox Code Playgroud)

有了这个:

p = calloc(1, sizeof(*p) + sizeof (p->u[0]));
if (p == NULL)
    return (NULL);
Run Code Online (Sandbox Code Playgroud)

为了进一步简化,由于您每次只创建联合的一个实例,因此不需要灵活的数组成员。只需像这样声明您的结构:

typedef struct  s_intersection{
  double       t1;
  double       t2;
  int id;
  union {
    t_sphere sph;
    t_cylinder cyl;
    t_triangle tri;
  };
} t_intersection;
Run Code Online (Sandbox Code Playgroud)

并创建一个像这样的实例:

t_intersection  *intersection(unsigned int geometric_figure_id, void *figure)
{
    t_intersection  *p;

    p = calloc(1, sizeof(*p));
    if (p == NULL)
        return (NULL);
    p->id = geometric_figure_id:
    if (geometric_figure_id == SPHERE_ID)
        p->sp = *(t_sphere *)figure;
    else if (geometric_figure_id == CYLINDER_ID)
        p->cy = *(t_cylinder *)figure;
    else if (geometric_figure_id == TRIANGLE_ID)
        p->tr = *(t_triangle *)figure;
    return (p);
}
Run Code Online (Sandbox Code Playgroud)