La memoria asignada en tiempo de compilación significa que el compilador resuelve en tiempo de compilación donde ciertas cosas se asignarán dentro del mapa de memoria del proceso.
Por ejemplo, considere una matriz global:
int array[100];
El compilador sabe en tiempo de compilación el tamaño de la matriz y el tamaño de una int
, por lo que conoce el tamaño completo de la matriz en tiempo de compilación. Además, una variable global tiene una duración de almacenamiento estático por defecto: se asigna en el área de memoria estática del espacio de memoria de proceso (sección .data / .bss). Dada esa información, el compilador decide durante la compilación en qué dirección de esa área de memoria estática estará la matriz .
Por supuesto que las direcciones de memoria son direcciones virtuales. El programa asume que tiene su propio espacio de memoria completo (desde 0x00000000 hasta 0xFFFFFFFF por ejemplo). Es por eso que el compilador podría hacer suposiciones como "Bien, la matriz estará en la dirección 0x00A33211". En tiempo de ejecución, la MMU y el sistema operativo traducen las direcciones a direcciones reales / de hardware.
Las cosas de almacenamiento estático inicializadas de valor son un poco diferentes. Por ejemplo:
int array[] = { 1 , 2 , 3 , 4 };
En nuestro primer ejemplo, el compilador solo decidió dónde se asignará la matriz, almacenando esa información en el ejecutable.
En el caso de cosas con valor inicializado, el compilador también inyecta el valor inicial de la matriz en el ejecutable, y agrega código que le dice al cargador del programa que después de la asignación de la matriz al inicio del programa, la matriz se debe llenar con estos valores.
Aquí hay dos ejemplos del ensamblaje generado por el compilador (GCC4.8.1 con destino x86):
Código C ++:
int a[4];
int b[] = { 1 , 2 , 3 , 4 };
int main()
{}
Ensamblaje de salida:
a:
.zero 16
b:
.long 1
.long 2
.long 3
.long 4
main:
pushq %rbp
movq %rsp, %rbp
movl $0, %eax
popq %rbp
ret
Como puede ver, los valores se inyectan directamente en el ensamblaje. En la matriz a
, el compilador genera una inicialización cero de 16 bytes, porque el Estándar dice que las cosas almacenadas estáticas deben inicializarse a cero por defecto:
8.5.9 (Inicializadores) [Nota]:
Cada objeto de la duración del almacenamiento estático se inicializa en cero al inicio del programa antes de que tenga lugar cualquier otra inicialización. En algunos casos, la inicialización adicional se realiza más tarde.
Siempre sugiero a las personas que desmonten su código para ver qué hace realmente el compilador con el código C ++. Esto se aplica desde las clases de almacenamiento / duración (como esta pregunta) hasta las optimizaciones avanzadas del compilador. Puede indicarle a su compilador que genere el ensamblado, pero existen herramientas maravillosas para hacerlo en Internet de manera amigable. Mi favorito es GCC Explorer .