2010-09-16 4 views
6

no entender por quéEl tamaño de una estructura con dos punteros vacíos es 4?

struct e{ 
    void * a; 
    void * b[]; 
} 

tiene sizeof (e) == 4 mientras

struct f{ 
    void * a; 
    void * b; 
} 

tiene sizeof (f) == 8.

+0

A [discusión de la legalidad del "struct hack" en ansi c] (http://stackoverflow.com/questions/3711233/). La búsqueda en "struct hack" en So no devuelve mucho interés en este momento, pero esa es la frase que está buscando. – dmckee

Respuesta

12

El segundo en la primera estructura no es un puntero, sino un FAM - miembro flexible de la matriz. Se usa cuando tiene un búfer largo y coloca un e al comienzo de ese búfer. A continuación, puede indexar la memoria restante que sigue al objeto e utilizando ese FAM y tratar esa memoria como una matriz de void*.

dice que el estándar (el subrayado por mí)

Como caso especial, el último elemento de una estructura con más de un miembro nombrado puede tener un tipo de matriz incompleta; esto se llama un miembro de matriz flexible. En la mayoría de las situaciones, el elemento de matriz flexible se ignora. 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 posterior que que implicaría la omisión.

Por ejemplo, las siguientes salidas de código 1 para la estructura exterior, sino 4 para la estructura con la FAM en GCC, debido a números enteros de acceso a la necesidad FAM a alinearse correctamente (en un límite de 4 bytes en este ejemplo)

struct A { 
    char a; 
}; 

struct B { 
    char a; 
    int flex[]; 
}; 

int main() { 
    printf("sizeof A: %d\nsizeof B: %d\n", 
     (int)sizeof(struct A), 
     (int)sizeof(struct B) 
    ); 

    struct B *b = malloc(sizeof *b + sizeof(int[3])); 
    b->a = 'X'; 
    b->flex[0] = 1; 
    b->flex[1] = 2; 
    b->flex[2] = 3; 
    free(b); 
} 
+0

Como compiló los contenidos en varias publicaciones y agregó un ejemplo, acepté su respuesta sobre la anterior. –

17
struct e{ 
    void * a; 
    void * b[]; 
//   ^^ 
} 

El [] en una estructura hace b un "miembro de matriz flexible" C99. Por lo tanto sizeof(e) contará el tamaño de tan sólo a, que es 4.

Desde C99 § 6.7.2.1/16:

Como caso especial, el último elemento de una estructura con más de un miembro nombrado puede tener un tipo de matriz incompleta; esto se llama 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 el miembro de matriz flexible se hubiera omitido, excepto que puede tener más relleno posterior que la omisión implicaría.

Sin embargo, cuando un operador . (o ->) tiene un operando izquierdo que es (un puntero) una estructura con un miembro de matriz flexible y el operando derecho nombra a ese miembro, se comporta como si ese miembro se reemplazara con el 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.

+1

¿Eso significa que no puedo acceder a él? –

+0

@Alan: No, todavía puede acceder a 'b'. – kennytm

+0

@ Alan: no; simplemente significa que sizeof() devuelve el resultado que observa. –

2

Esto es porque el segundo struct utiliza una matriz miembro flexible.La explicación del tamaño del resultado está en Wikipedia.

1

void * b[]; no es válido en C89, por lo que significa que está utilizando un compilador C99.

C99 introdujo un medio para definir el "truco struct": ahora se llama "miembro de la matriz flexible" y la memoria antes de que se asigna, su tamaño es 0.

+0

Esto también era importante de observar porque estaba tratando de seguir con C89. ¡Gracias! –

0

Debido a que el primero no está declarando cualquier espacio para los punteros en "b".

Cuestiones relacionadas