Este es el código C99:
typedef struct expr_t
{
int n_children;
foo data; // Maybe whatever type with unknown alignment
struct expr_t *children[];
} expr_t;
Ahora, ¿cómo asigno memoria?
expr_t *e = malloc (sizeof (expr_t) + n * sizeof (expr_t *));
o
expr_t *e = malloc (offsetof (expr_t, children) + n * sizeof (expr_t *));
?
Es sizeof
incluso garantizado para trabajar en un tipo con miembro de matriz flexible (GCC lo acepta)?

lococasta
expr_t *e = malloc (sizeof (expr_t) + n * sizeof (expr_t *));
está bien definido en C99. De la especificación C99 6.7.2.1.16:
Como caso especial, el último elemento de una estructura con más de un miembro con nombre puede tener un tipo de matriz incompleta; esto se denomina miembro de matriz flexible. En la mayoría de las situaciones, se ignora el miembro de matriz flexible. En particular, el tamaño de la estructura es como si se hubiera omitido el miembro de matriz flexible, excepto que puede tener más relleno final de lo que implicaría la omisión.

Blagovest Büyükliev
Si el compilador acepta la declaración de una estructura con un miembro de matriz flexible, el sizeof
El operador para esa estructura debería generar el tamaño de la estructura como si el miembro de matriz flexible no existiera.
La asignación correcta de tal estructura sería:
expr_t *e = malloc (sizeof(expr_t) + n * sizeof(struct expr_t *));
Todavía puede hacer este truco incluso si el compilador no admite miembros de matriz flexibles. Simplemente declare que el miembro de la matriz de su estructura tiene un tamaño de 1
y luego asignar n - 1
elementos en lugar de n
.
Sí, está garantizado que funciona. C99 §6.7.2.1/16 dice “el tamaño de la estructura será igual al desplazamiento del último elemento de una estructura idéntica que reemplaza el miembro de matriz flexible con una matriz de longitud no especificada”. Entonces
sizeof(expr_t)
es igual al valor queoffsetof(expr_t, children)
si hubieras redefinidochildren
ser una matriz de cualquier tamaño determinado.– Adam Rosenfield
1 oct 2012 a las 21:03