6.6.- Apuntadores y arreglos
Como se mencionó en la unidad 5, el tema de arreglos está íntimamente ligado al de apuntadores; tanto que es posible intercambiarlos en la solución de un problema.
El nombre de un arreglo corresponde al de un apuntador que almacena un valor constante. Este valor constante es la dirección de memoria del primer elemento del arreglo.
Por ejemplo :
int calif[]={100,90,95,80,90}; // Declaración e
// inicialización
// de un arreglo
// de 5 enteros
se puede representar con la figura 6.6.
Figura 6.6.- El arreglo calif[ ] en la pila.
En realidad, el lenguaje manejará al arreglo a través de un apuntador llamado calif, el cual tiene almacenado el valor 65494, que a su vez corresponde a la dirección de inicio del elemento calif[0].
La representación del apuntador calif, en la zona de variables globales de la memoria RAM, es la siguiente :

En el listado 6.7 se presenta el manejo del arreglo calif[ ], a través de la notación de arreglos, y en el listado 6.8 el manejo con la notación de apuntadores.
#include <iostream.h>
void main()
{
int calif[] = { 100,90,95,80,90};
for(int i=0 ; i <5 ; i++) //Notación de arreglos. cout << "\n" << calif[i] ; }
Listado 6.7.- Manejo de calif[] , notación de arreglos.
#include <iostream.h>
void main()
{
int calif[] = { 100,90,95,80,90};
for(int i=0 ; i <5 ; i++) // Notación de apuntadores cout << "\n" << *(calif+i) ; }
Listado 6.8.- Manejo de calif[] , notación de apuntadores.
Como puede observarse, la única diferencia entre los listados 6.7 y 6.8 es que el primero utiliza calif[i] y el segundo *(calif+i).
Debido a que la ejecución de los programas de ambos listados producen resultados iguales, se deduce que:
calif[i] == *(calif+i)
Para entender esto que a simple vista no es obvio, revisaremos algunos conceptos:
1.- El nombre del arreglo corresponde al de un apuntador que apunta
al primer elemento del arreglo, por lo que:
calif apunta a calif[0]
Visto gráficamente :
2.- Para hacer referencia a un elemento específico del arreglo,
se toma como base la dirección del primer elemento y, con el
subíndice del elemento específico, se calcula su dirección.
Por ejemplo, para referirse al segundo elemento del arreglo
puede procederse así :
calif[1] // Notación de arreglos
ó
*(calif+1) // Notación de apuntadores, donde
la expresión calif+1sirve para calcular la dirección del
elemento que está una posición más allá del elemento
apuntado por calif.
Para referirse a calif[2] ( tercer elemento ), puede
escribirse:
*(calif+2)
Lo que significa: "El objeto que se encuentra dos posiciones
después del objeto apuntado por calif".
En este caso, una posición es el espacio requerido por cada
uno de los elementos, de tal manera que, si calif apunta a la
dirección 65494, entonces calif+2 es la expresión que calcula
la dirección 65498.
La figura 6.7 muestra los elementos del arreglo calif[] con
sus nombres en notación de arreglos y en notación de
apuntadores.
Figura 6.7.- El arreglo calif[] en la pila. Notación
en arreglos y en apuntadores.
De lo anterior, se infiere la regla:
calif[i] == *(calif+i)
por lo que:
&calif[i] == calif+i
Esto es que, la dirección del i-ésimo elemento de un arreglo se calcula sumándole el subíndice a la dirección del primer elemento.
Como otro ejemplo, supongamos la siguiente declaración correspondiente a un arreglo de 10 elementos de tipo float.
float* sueldo[10];
Si la dirección del primer elemento es 65494, entonces:
&sueldo[5] es igual a :
sueldo+5 = 65494 + ( 5 * 4 ) = 65514
^
|
Tamaño de float ---------|
que corresponde a la dirección del elemento que se encuentra 5 posiciones más adelante de aquél apuntado por sueldo.
Como regla, podemos establecer que el subíndice se refiere a la posición del elemento en el arreglo. Es por esto que al calcular la dirección por medio del subíndice, éste debe multiplicarse por el número de bytes que representan el tamaño de cada elemento ( dado por el tipo utilizado en la declaración del arreglo ).