Universidad Carlos III de Madrid

Grado en Ing. Telemática/Sist. Audiovisuales/Sist. de Comunicaciones

Arquitectura de Sistemas

Septiembre 2012 - Enero 2013

6. Tablas y punteros

Aunque el concepto de tabla en un lenguaje de programación es intuitivo, en C las tablas se manipulan de una forma especial que debe ser entendida para evitar errores al combinar su uso con memoria dinámica. Para el lenguaje de programación C, una tabla se representa internamente sólo como la dirección de memoria a partir de la cual está almacenado su primer elemento. Otra forma de verlo, en C se define una tabla de 100 elementos de tipo T como T tabla[100], pero una vez definida (y reservado su espacio correspondiente ya sea en la memoria global o en la pila), en adelante, el nombre de la tabla y la dirección de su primer elemento es exactamente lo mismo. Esta particularidad de C se puede resumir diciendo que para toda tabla en C la siguiente expresión es siempre cierta:

tabla == &tabla[0]

La principal consecuencia es que cuando es preciso reservar espacio en memoria dinámica para una tabla, la reserva devuelve un puntero, pero este puede utilizarse directamente como una tabla. Por ejemplo, el siguiente código crea una tabla de tantos elementos como indica la variable size y los inicializa:

struct element 
{
  float number1;
  int number2;
  char letter;
};

struct element *table;

table = (struct element *)malloc(sizeof(struct element) * size);
for (i = 0; i < size; i++) 
{
  table[i].number1 = 0.0;
  table[i].number2 = 10;
  table[i].letter = 'B';
}

Nótese que el acceso a los elementos de la tabla, tras incluir el índice entre corchetes, se realiza como una estructura, y no como un puntero.

Por lo tanto existe una gran relación entre punteros y tablas. Con una variable puntero que apunta al primer elemento de una tabla, se pueden realizar las mismas operaciones (y con la misma notación) que las que se pueden hacer con la tabla definida. Sin embargo, no todas las operaciones que se pueden realizar con un puntero son válidas para realizarlas con una tabla. Así a un puntero se le puede asignar otro puntero o la dirección inicial de una tabla, mientras que sin embargo a una tabla declarada no se le puede asignar otro puntero o la dirección inicial de otra tabla. Esto es porque al declarar una tabla su dirección permanece fija, mientras que el puntero puede admitir nuevas asignaciones. El siguiente código ilustra esta situación:

1
2
3
4
5
#define SIZE 30
char cadena1[SIZE];
char *cadena2;
cadena1 = "Pulsa espacio para continuar"; /* Incorrecto */
cadena2 = "Pulsa espacio para continuar"; /* Correcto */

La línea 4 es incorrecta porque a la tabla cadena1 no se le puede asignar una dirección nueva, ya se le asigna al ser declarada. Por el contrario, cadena2 se declara como puntero, y sí se le puede asignar una dirección cualquiera, y en la línea 5 se le asigna la de la cadena Pulsa espacio para continuar.