C-Sim - Simulador de manejo de memoria de C

Referencias

Introducción

C-Sim es un simulador de gestión de memoria de C. Su objetivo es ser un método didáctico de mostrar cómo se almacenan las variables y funcionan los punteros.

Manejo básico del simulador

El programador mantiene una barra de herramientas en la parte superior, una línea de entrada en la parte inferior, y una zona intermedia donde se visualiza, de izquierda a derecha, el árbol de variables, la representación de la memoria o el diagrama de variables, y finalmente, el histórico de sentencias introducidas.

El subconjunto de C soportado

C-Sim es capaz de manejar los siguientes tipos de datos básicos:
No solo es posible crear variables de estos tipos, sino además punteros a las mismas.

Trabajando con C-Sim

Un ejemplo introductorio sería el siguiente. Introduzca las siguientes sentencias en el programa:
int a = 5
int
b = 6
No es necesario añadir punto y coma (;) al final, C-Sim asume que existen. En este caso aparece un diagrama que muestra dos cajas en la parte superior de la ventana, cada una dedicada a las dos variables creadas. En la parte superior de la caja aparece el tipo, a continuación el tamaño en bytes, y la dirección de memoria entre corchetes. Dentro de la caja, aparece el valor actual de la variable, y debajo de ella, el nombre de la misma.
Variable

Ahora es posible crear un puntero:
int * ptr = &a
El puntero se representa de manera muy similar a la variable, sólo que en su tipo aparecerá int * en lugar de int. Finalmente, una flecha aparecerá uniendo las cajas del puntero y de la variable. En caso de que el puntero tenga valor nulo (NULL o 0), entonces la flecha aparecerá apuntando a una toma de tierra.

Se puede utilizar la función printf() para mostrar un valor. Por ejemplo, tecleando:

printf( *ptr )

Se imprimirá el valor de la variable a (5) en la salida (output) inferior.

Punteros

Como ya se ha explicado, los punteros se crean de la misma forma que se crean en C. Pueden ser inicializados utilizando la dirección de una variable existente, o incluso una constante en hexadecimal o decimal. Dado el siguiente código;
int a = 5
int
b = 6
int * ptr = &a
Ptr
El valor del puntero ptr debe ser el mismo que la dirección de la variable apuntada, a (que aparece entre corchetes en la parte superior de su caja). Ahora es posible realizar cambios sobre la variable a sin utilizarla directamente, como por ejemplo:
*ptr = 3
printf( a )
El código anterior imprimirá 3 en la salida inferior.

Referencias

Aunque no son propias de C, sino de C++, C-Sim soporta también el uso de referencias, que interpreta como punteros especiales. Estos punteros no precisan de la sintaxis habitual (asterisco) para acceder al valor apuntado, y de hecho impersonan a la variable apuntada incluso cuando se trata de obtener su dirección.
Ref
int a = 5
int
&ref = a
ref = 7
int * ptr = &ref
printf( *ptr )
El código anterior imprimirá 7 en la salida inferior.

Comprensión del manejo de memoria con punteros

Los punteros guardan dos informaciones valiosas dentro de sí: la dirección a la que apuntan, y el tipo al que pertenecen. Lo segundo sirve para saber cuántos bytes de memoria manejar cuando se accede a la dirección.
int ptr a char
int a = 5
char ch = 'a'
int * ptr = 90
printf( ch )
printf( *ptr )
En el ejemplo más arriba, si en lugar de la tercera instrucción se intentara int * ptr = &ch, esta no funcionaría, pues un puntero a entero no puede apuntar a un puntero a char. Sin embargo, en el ejemplo se fuerza esta circunstancia, asignándole directamente a ptr la dirección de memoria que ocupa ch mediante una constante numérica. A pesar de que el puntero apunta a un caracter, como debe tomar 4 bytes para un entero (en un arquitectura de 32 bits), toma el primer byte con el valor 65 (la A mayúscula) y los tres siguientes bytes, que no se sabe lo que contienen. Así, el valor impreso para *ptr y ch no coincide.