2011-01-09 17 views
7

Consideremos el siguiente código:entendimiento C tamaño struct ++

struct CExample { 
    int a; 
}    

int main(int argc, char* argv[]) { 

    CExample ce1; 
    CExample ce2; 

    cout << "Size:" << sizeof(ce1) << " Address: " << &ce1 << endl; 
    cout << "Size:" << sizeof(ce2) << " Address: " << &ce2 << endl; 

    CExample ceArr[2]; 
    cout << "Size:" << sizeof(ceArr[0])<< " Address: "<< &ceArr[0] <<endl; 
    cout << "Size:" << sizeof(ceArr[1])<< " Address: "<< &ceArr[1] <<endl; 

    return 0; 
} 

ejemplo de salida:
ce1: Tamaño = 4, Dirección: 0039FAA0
ce2: Tamaño = 4, Dirección: 0039FA94
ceArr [0] : Tamaño = 4, Dirección: 0039FA84
ceArr [1]: Tamaño = 4, Dirección: 0039FA88

Con el código hay un 12-byte entre las direcciones de los dos primeros objetos (CE1 y CE2) pero hay es solo una apuesta de diferencia de 4 bytes ween los objetos en la matriz.

Pensé que la alineación de datos tendría algo que ver con el problema, pero todavía estoy perplejo. ¿Alguna idea de lo que está pasando aquí?

+2

Cuál es la salida de los anteriores? ¿Te molesta publicar eso también en el código? –

Respuesta

15

Porque se requiere que los objetos en una matriz sean contiguos. Los objetos declarados consecutivamente en la pila (en el código fuente, no en la máquina) no son [obligados a ser contiguos], aunque pueden serlo.

+1

Bueno, ** pueden ** estar, pero no están ** obligados ** a estar. –

+0

@Billy Eso es lo que dije. –

+0

Lo siento ... malinterpreté eso. La segunda oración, leída por sí misma, parece decir que nunca son contiguas. Lo sentimos :( –

6

La norma no dice nada al respecto. El compilador puede insertar libremente el relleno que desee entre los elementos.

(Si tuviera que adivinar, diría que que su compilador implementa algún tipo de pila de protección/canario en el modo de depuración (y que se compila en modo de depuración))

+0

Posible, se está reservando el espacio de objetos temporales, (o tal vez hay un huevo de Pascua? –

+0

Sí, tienes razón! He intentado compilar en modo de lanzamiento y funcionó como esperaba! – kiokko89

0

La razón es que, en la mayoría de las arquitecturas, cargas desalineadas son lentas. Vea la entrada de Wikipedia en data structure alignment para una buena explicación. El compilador coloca cada una de sus estructuras de datos al comienzo de una palabra de datos. Sin embargo, en matrices, los elementos se colocan contiguamente en la memoria (como requiere el estándar C++).

+2

No conozco ninguna arquitectura que requiera alineación en los límites de 12 bytes. ¿Conoces alguna? –

+0

No, OP no publicó la salida (IIRC), lo que muestra que no es un problema de alineación. significaba 12 bytes = 16 bytes menos los 4 bytes del objeto original. Cuando lo compilé en mi Mac, obtuve la diferencia de 16 bytes esperados. @ kiokko89: no es que importe, pero ¿qué compilador/plataforma está usando? – EmeryBerger

+0

estoy usando el compilador de Visual Studio con una máquina x64 (lo siento otra vez por mi mal inglés) – kiokko89

1

El compilador no solo usa la pila para mantener sus variables locales, sino que también la usa, por ejemplo, para pasar argumentos, y parte de la sobrecarga causada por std::cout. Para eso se usa el espacio extra entre tus variables.

Si en lugar de hacer sus variables de static, como este:

static CExample ce; 
static CExample ce2; 

static CExample ceArr[2]; 

... las variables serán colocados en la memoria BSS su lugar, y la alineación es más probable que sea el esperado.

La razón por la cual se embalan matrices, y otros objetos sueltos no lo son, se clarifica por otras respuestas ...