¿Cuál es el propósito de una matriz de longitud cero en una estructura?

Cuando miro el código del kernel de Linux, encontré el siguiente código:

struct thread_info { struct task_struct *task; struct exec_domain *exec_domain; unsigned long flags; __u32 status; __u32 cpu; int preempt_count; mm_segment_t addr_limit; struct restart_block restart_block; void __user *sysenter_return; unsigned long previous_esp; __u8 supervisor_stack[0]; }; 

Tenga en cuenta que la última variable “supervisor_stack”, es una matriz de longitud cero, ¿cuál es el uso de la misma? ¡Gracias por adelantado!

Es la versión anterior a C99 de un miembro de matriz flexible, ofrecido por GCC como una extensión.

La forma C99 es definir el miembro de matriz flexible con corchetes vacíos,

 __u8 supervisor_stack[]; 

Se usa para almacenar datos cuya cantidad no es constante contigua a la estructura. La memoria se asigna en la forma

 struct foo *ptr = malloc(sizeof *ptr + whatever_is_needed); 

En el párrafo 18 de 6.7.2.1, la norma (borrador N1570) los describe:

Como un caso especial, el último elemento de una estructura con más de un miembro nombrado puede tener un tipo de matriz incompleto; esto se llama un miembro de matriz flexible. En la mayoría de las situaciones, el miembro de matriz flexible se ignora. En particular, el tamaño de la estructura es como si se hubiera omitido el miembro flexible de la matriz, excepto que puede tener más relleno posterior de lo que implicaría la omisión. Sin embargo, cuando a . (o -> ) el operador tiene un operando izquierdo que es (un puntero) una estructura con un miembro de matriz flexible y el operando derecho nombra ese miembro, se comporta como si ese miembro se reemplazara con la matriz más larga (con el mismo tipo de elemento) ) que no haría la estructura más grande que el objeto al que se accede; el desplazamiento de la matriz seguirá siendo el del miembro de matriz flexible, incluso si esto difiriera del de la matriz de reemplazo. Si esta matriz no tiene elementos, se comporta como si tuviera un elemento, pero el comportamiento no está definido si se intenta acceder a ese elemento o generar un puntero pasado.

Es un truco C común declarar lo que se puede llamar una matriz de longitud variable (donde se define el tamaño en el momento de la asignación)

Ejemplo:

 struct line { int length; char contents[0]; }; struct line *thisline = (struct line *) malloc (sizeof (struct line) + this_length); thisline->length = this_length; 

De esta forma, tiene una definición de estructura de sus datos, que también almacena la longitud de la matriz para fines obvios de convección, pero no está limitado por el tamaño fijo que generalmente se asocia con una estructura

Ejemplo tomado de aquí (también más información)