C matrices flexibles vs punteros

struct ss { char foo[]; char bar[3]; int bazSize; char baz[]; } 

En lo anterior, foo es claramente un puntero de 4 u 8 bytes de largo. bar es una matriz, de 3 bytes de longitud. baz solía ser un puntero, 8 bytes de largo. Pero en C99 baz es una matriz flexible. (Tradicionalmente definido como baz [0].)

¿Cuales son las normas? ¿Cómo sabe el comstackdor que foo es un tipo de cosa completamente diferente a baz? ¿Cómo no puede esto simplemente romper cualquier código que tenga un puntero al final de una estructura? ¿Es [] ahora diferente de *?

Su statement de estructura es incorrecta: char foo[]; solo puede aparecer como el último miembro, y falta un ; al final. Aquí está la statement correcta:

 struct ss { char *foo; char bar[3]; int bazSize; char baz[]; }; 

Tenemos un puntero foo y una matriz flexible baz al final. Al asignar una estructura de este tipo desde el montón, el espacio real para el último miembro debe ser conocido y no puede cambiarse sin reasignar a la estructura cuya estructura puede complicarse si la estructura a la que se hace referencia desde otros lugares. Las matrices flexibles ahorran espacio pero no son flexibles en absoluto.

Ventajas de la matriz flexible:

  • ahorra espacio
  • guardar una dirección indirecta
  • asignar en un solo paso
  • baz nunca es NULL

Por el contrario, hacer de baz un puntero requiere una asignación separada de la matriz a la que apunta. Esta desventaja en tamaño, código y velocidad viene con compensaciones.

Ventajas de la versión de puntero:

  • baz puede ser NULL para no especificar datos.
  • baz se puede asignar a pedido, cuando se conoce el tamaño real.
  • baz se puede reasignar fácilmente.

Entonces, lo que debes usar depende de cómo uses estas estructuras. La syntax en el punto de uso es la misma, pero el comstackdor ha visto la statement real y generará el código apropiado.

Primero, debes inicializar foo y baz para que el código se compile realmente. Entonces queda claro para el comstackdor cuál es la diferencia entre los dos.

El problema es que char *foo y char foo[] son solo lo mismo en algunos contextos (como statement de parámetros de función) y no en otros (como declaraciones de campo de estructura).

(No he hackeado C durante mucho tiempo.)