Para abordar la pregunta que ha publicado en varios comentarios (que creo que debería editar en su publicación):
Lo que no entiendo es cómo sabe la computadora cuando lee el valor de una variable y una dirección como 10001 si es un int o char. Imagine que hago clic en un programa llamado anyprog.exe. Inmediatamente el código comienza a ejecutarse. ¿Este archivo exe incluye información sobre si las variables se almacenan como en o char?
Así que vamos a ponerle un código. Digamos que escribes:
int x = 4;
Y supongamos que se almacena en la RAM:
0x00010004: 0x00000004
La primera parte es la dirección, la segunda parte es el valor. Cuando su programa (que se ejecuta como código de máquina) se ejecuta, todo lo que ve 0x00010004
es el valor 0x000000004
. No 'conoce' el tipo de estos datos, y no sabe cómo 'se supone' que se utilizarán.
Entonces, ¿cómo determina su programa lo correcto? Considera este código:
int x = 4;
x = x + 5;
Tenemos una lectura y una escritura aquí. Cuando su programa lee x
de la memoria, encuentra 0x00000004
allí. Y su programa sabe agregarlo 0x00000005
. Y la razón por la cual su programa 'sabe' que esta es una operación válida, es porque el compilador asegura que la operación es válida a través de la seguridad de tipo. Su compilador ya ha verificado que puede agregar 4
y 5
juntos. Entonces, cuando se ejecuta su código binario (el exe), no tiene que hacer esa verificación. Simplemente ejecuta cada paso a ciegas, suponiendo que todo esté bien (las cosas malas suceden cuando en realidad están bien, no están bien).
Otra forma de pensar es así. Te doy esta información:
0x00000004: 0x12345678
Mismo formato que antes: dirección a la izquierda, valor a la derecha. ¿De qué tipo es el valor? En este punto, usted conoce tanta información sobre ese valor como su computadora cuando ejecuta código. Si le dijera que agregue 12743 a ese valor, podría hacerlo. No tienes idea de lo que las repercusiones de esa operación serán en todo el sistema, pero la adición de dos números es algo que es realmente bueno en, por lo que podría hacerlo. ¿Eso hace que el valor sea un int
? No necesariamente: todo lo que ves son dos valores de 32 bits y el operador de suma.
Tal vez parte de la confusión es recuperar los datos. Si tenemos:
char A = 'a';
¿Cómo sabe la computadora mostrar a
en la consola? Bueno, hay muchos pasos para eso. El primero es ir a A
la ubicación de s en la memoria y leerlo:
0x00000004: 0x00000061
El valor hexadecimal para a
en ASCII es 0x61, por lo que lo anterior podría ser algo que vería en la memoria. Entonces, nuestro código de máquina conoce el valor entero. ¿Cómo sabe convertir el valor entero en un carácter para mostrarlo? En pocas palabras, el compilador se aseguró de poner todos los pasos necesarios para hacer esa transición. Pero su computadora (o el programa / exe) no tiene idea de cuál es el tipo de datos. Ese valor de 32 bits podría ser cualquier cosa - int
, char
, la mitad de una double
, un puntero, que forma parte de una matriz, parte de una string
, parte de una instrucción, etc.
Aquí hay una breve interacción que su programa (exe) podría tener con la computadora / sistema operativo.
Programa: quiero comenzar. Necesito 20 MB de memoria.
Sistema operativo: encuentra 20 MB de memoria libre que no están en uso y los entrega
(La nota importante es que esto podría volver algún 20 MB libres de memoria, ni siquiera tienen que ser contiguos. En este punto, el programa ahora puede operar dentro de la memoria que tiene sin hablar con el sistema operativo)
Programa: voy a suponer que el primer punto en la memoria es una variable entera de 32 bits x
.
(El compilador se asegura de que los accesos a otras variables nunca toquen este punto en la memoria. No hay nada en el sistema que diga que el primer byte es variable x
, o que la variable x
es un número entero. Una analogía: tienes una bolsa. Le dices a la gente que solo pondrás bolas de color amarillo en esta bolsa. Cuando alguien más tarde saque algo de la bolsa, sería sorprendente que sacara algo azul o un cubo, algo salió terriblemente mal. Lo mismo ocurre con las computadoras: su el programa ahora supone que el primer punto de memoria es la variable x y que es un número entero. Si alguna vez se escribe algo más sobre este byte de memoria o se supone que es otra cosa, ha sucedido algo horrible. El compilador asegura que este tipo de cosas no no suceda)
Programa: ahora escribiré 2
en los primeros cuatro bytes donde supongo que x
está en.
Programa: quiero agregar 5 a x
.
Lee el valor de X en un registro temporal
Agrega 5 al registro temporal
Almacena el valor del registro temporal de nuevo en el primer byte, que todavía se supone que es x
.
Programa: voy a asumir que el siguiente byte disponible es la variable char y
.
Programa: escribiré a
en variable y
.
Programa: quiero mostrar el contenido de y
Lee el valor en el segundo punto de memoria
Utiliza una biblioteca para convertir del byte a un carácter.
Utiliza bibliotecas de gráficos para alterar la pantalla de la consola (configuración de píxeles de negro a blanco, desplazamiento de una línea, etc.)
(Y continúa desde aquí)
Lo que probablemente te está colgando es: ¿qué sucede cuando el primer lugar en la memoria ya no está x
? o el segundo ya no es y
? ¿Qué sucede cuando alguien lee x
como un char
o y
como un puntero? En resumen, suceden cosas malas. Algunas de estas cosas tienen un comportamiento bien definido, y algunas tienen un comportamiento indefinido. El comportamiento indefinido es exactamente eso: cualquier cosa puede suceder, de la nada a fallar el programa o el sistema operativo. Incluso el comportamiento bien definido puede ser malicioso. Si puedo cambiar x
a un puntero a mi programa y hacer que su programa lo use como puntero, entonces puedo hacer que su programa comience a ejecutar mi programa, que es exactamente lo que hacen los piratas informáticos. El compilador está ahí para ayudar a asegurarnos de que no lo usemos int x
comostring
y cosas de esa naturaleza. El código de la máquina en sí no conoce los tipos, y solo hará lo que las instrucciones le indiquen. También se descubre una gran cantidad de información en tiempo de ejecución: ¿qué bytes de memoria puede usar el programa? ¿ x
Comienza en el primer byte o el 12?
Pero puedes imaginar lo horrible que sería escribir programas como este (y puedes hacerlo en lenguaje ensamblador). Empiezas por 'declarar' tus variables: te dices a ti mismo que el byte 1 es x
, el byte 2 es y
, y a medida que escribes cada línea de código, cargando y almacenando registros, tú (como humano) tienes que recordar cuál es x
y cuál uno es y
, porque el sistema no tiene idea. Y usted (como humano) tiene que recordar qué tipos x
y qué y
son, porque una vez más, el sistema no tiene idea.