Al usar lenguajes de alto nivel como Python, no es necesario conocer a fondo cómo funcionan las listas para resolver problemas comunes. Sin embargo, entender su estructura te ayuda a que el código sea menos misterioso y te permite comprender mejor lo que ocurre detrás.
Arrays en C
Las listas se basan en el concepto de arrays. Es útil aprender cómo funcionan los arrays en un lenguaje como C, ya que es simple, fácil de entender y está muy cerca del hardware, lo que permite ver cómo se gestionan los datos. Cuando usamos tipos de datos simples como cadenas o números, es fácil imaginar que se asigna una cantidad de memoria específica para cada valor. Pero, ¿cómo se asigna la memoria para un array? A nivel de hardware, no existe un concepto como array. Un array es simplemente un bloque de memoria que se calcula con la fórmula:
número de elementos * cantidad de memoria por elemento
De esto, se derivan dos conclusiones importantes:
- El tamaño del array es fijo. Los arrays dinámicos, que pueden cambiar de tamaño, se manejan a nivel del lenguaje de programación, no del hardware.
- Todos los elementos del array son del mismo tipo y ocupan la misma cantidad de memoria, lo que permite calcular la dirección de un elemento simplemente multiplicando el índice por la cantidad de memoria que ocupa cada elemento.
Un índice en un array es el desplazamiento desde el inicio del bloque de memoria donde están los datos. La dirección de un elemento en un array se calcula con la fórmula:
índice * cantidad de memoria por cada elemento
Veamos un ejemplo en C:
// Inicialización de un array de cinco elementos de tipo int
// Supongamos que int ocupa 2 bytes
// La cantidad total de memoria asignada para el array es: int * 5 = 2 * 5 = 10 bytes
int numbers[] = {19, 10, 8, 17, 9};
numbers[3]; // 17
Si int ocupa 2 bytes, la dirección del elemento en el índice 3 se calcula así: dirección inicial + 3 * 2. Aquí tienes el cálculo de las direcciones de los elementos en el array numbers:
// Primer elemento
// Dirección inicial + 2 * 0 = Dirección inicial
numbers[0]; // 19
// Dirección inicial + 2 * 1 = Dirección inicial + 2
// Es decir, avanzamos 2 bytes.
numbers[1]; // 10
// Dirección inicial + 2 * 2 = Dirección inicial + 4
// Es decir, avanzamos 4 bytes
numbers[2]; // 8
// Último elemento
// Dirección inicial + 2 * 4 = Dirección inicial + 8
// Es decir, se avanza 8 bytes
// Y el elemento en sí ocupa 2 bytes. En total, son exactamente 10.
numbers[4]; // 9
Esto explica por qué los índices de un array empiezan en cero: 0 significa que no hay desplazamiento desde el inicio del array.
Sin embargo, no todos los datos ocupan el mismo espacio. ¿Cómo se almacena un array de cadenas? Las cadenas tienen diferentes longitudes, por lo que necesitan distintas cantidades de memoria. En C, una forma de manejar esto es usando un array de arrays, recordando que una cadena en C es un array de caracteres. Los arrays anidados deben tener un tamaño fijo, por lo que el truco es que ese tamaño sea suficiente para las cadenas que queremos almacenar.
// Un array de tres elementos, cada uno de los cuales es un array de 10 elementos
// Esto significa que aquí se pueden almacenar 3 cadenas de no más de 10 caracteres
char strings[3][10] = {
"spike",
"tom",
"jerry"
};
strings[0]; // spike
Seguridad
A diferencia de lenguajes de alto nivel, donde el sistema te protege de acceder fuera de los límites de un array, en C puedes hacerlo sin recibir un error inmediato. Esto puede llevar a comportamientos inesperados o incluso a fallos de seguridad 🔓 si se accede a datos que están fuera del array. Acceder fuera de los límites de un array es una técnica usada frecuentemente por hackers para comprometer la seguridad de los programas.
Arrays en lenguajes dinámicos
En lenguajes dinámicos como Python, las listas funcionan de manera más compleja que en C. Los tipos de datos se determinan en tiempo de ejecución, lo que significa que un array no puede funcionar igual que en C. En lugar de almacenar los datos directamente, los arrays en estos lenguajes almacenan referencias a los datos. Esto hace que no importe qué tipo de dato se almacena, ya que lo que realmente se guarda es una dirección en memoria. Este enfoque hace que los arrays sean más flexibles, pero también más lentos 🐢
Además, los arrays en lenguajes dinámicos son capaces de cambiar de tamaño mientras el programa se ejecuta. Cuando un array necesita más espacio, el intérprete crea un nuevo array más grande (generalmente el doble de grande) y transfiere todas las referencias al nuevo array. Esto facilita el trabajo del desarrollador, pero también afecta la velocidad.
Para acceder completo a curso necesitas un plan básico
El plan básico te dará acceso completo a todos los cursos, ejercicios y lecciones de Códica, proyectos y acceso de por vida a la teoría de las lecciones completadas. La suscripción se puede cancelar en cualquier momento.