Todo se hace en "secciones". Donde va una sección depende de su uso. Lo que se pone en una sección, nuevamente, depende de su uso.
En general, obtienes dos secciones de "datos": .data y .rodata. .data se almacena en la memoria RAM y es de lectura y escritura. .rodata se almacena en Flash y es de solo lectura.
Las cosas que son "const" generalmente terminan en .rodata. Los literales (cadena, numérico, etc.) también terminan en .rodata.
Por ejemplo, estos normalmente se almacenan en Flash:
const char *foo = "foo";
const int bar = 234;
"baz" (string literal)
Estos se almacenarán en la memoria RAM:
char foo[10];
int bar;
Pero, por supuesto, puede ser más específico de MCU, especialmente cuando se accede a la arquitectura Harvard (espacios de direcciones de RAM / Flash divididos), donde el acceso a los datos almacenados en Flash puede ser más una tarea especial y no se realiza como variables normales . Por ejemplo, el const char *foo="foo";
se copiaría en la RAM para facilitar el acceso durante la inicialización del programa.
Cuando asigna una variable de cualquier tamaño dentro de una función, como:
void func() {
char mybuf[100];
}
la variable se asignará como parte de la pila (o un sistema similar a una pila emulada que usa variables estáticas en MCU con una pila de hardware limitada, como PIC de gama baja de 8 bits). Tan pronto como regrese de la función, se reclamará todo el espacio de la pila.
Sin embargo, si lo asigna utilizando malloc ():
void func() {
char *mybuf = malloc(100);
}
se asignará en el montón, y es su responsabilidad reclamar ese espacio usando free ().
La palabra clave register
, como en:
int register foo;
si se puede asignar un registro, almacenará los datos únicamente dentro de ese registro asignado. Nunca tocará la memoria RAM, y en consecuencia, se ejecutará más rápido. Sin embargo, si no se puede asignar un registro (todos están en uso en el código), la palabra clave de registro se ignorará y la variable se asignará en la RAM de manera normal. Una cosa a tener en cuenta:
char register *foo;
Eso solo mantendrá el puntero a los datos en un registro, no los datos en sí. Los datos en sí seguirán en RAM.
Sin embargo, en general, el uso de la palabra clave register
está mal visto ya que el optimizador del compilador generalmente hace un mejor trabajo, y el uso de register
puede hacer que otras partes de su código no se optimicen también. terminan siendo más complejos de lo que serían de otra manera.