CAPÍTULO 7: Más sobre Arrays Multidimensionales

En el capítulo anterior vimos que lo siguiente
    #define ROWS 5
    #define COLS 10

    int multi[ROWS][COLS];
permite acceder a los elementos del array multi mediante:
    multi[row][col]
o mediante:
    *(*(multi + row) + col)
Para entenderlo mejor, cambiemos
    *(multi + row)
por X como en:
    *(X + col)
Ahora vemos que X es como un puntero porque la expresión es desreferenciada y sabemos que col es un entero. Aquí estamos utilizando "aritmética de punteros", y al tratarse de un array de enteros, la dirección donde apunta (por ej. el valor de) X + col + 1 debe ser mayor que la dirección X + col por una diferencia de sizeof(int).

Ya sabemos como se guarda en memoria un array de dos dimensiones, y por tanto podemos determinar que en la expresión multi + row anterior, multi + row + 1 debe incrementarse por el valor necesario para "apuntar" a la siguiente línea, que en este caso es COLS * sizeof(int).

Esto quiere decir que para la evaluación correcta en tiempo de ejecución de la expresión *(*(multi + row) + col) el compilador debe generar el código teniendo en cuenta el valor de COLS (la segunda dimensión). Tanto la versión con punteros como la versión con arrays multi[row][col] son equivalentes.

Por tanto, para evaluar la expresión dada, se necesitan 5 valores:

  1. La dirección del primer elemento del array, que es el valor devuelto por la expresión multi, es decir, el nombre del array.
  2. El tamaño del tipo de los elementos del array, en este caso sizeof(int).
  3. La segunda dimensión del array.
  4. El valor específico del índice de la primera dimensión, que en este caso es row.
  5. El valor específico del índice de la segunda dimensión, que en este caso es col.
Con todo esto, vamos a diseñar una función para manipular los valores de los elementos del array declarado anteriormente. Por ejemplo, podemos iniciar todos los elementos del array multi con el valor 1.

    void set_value(int m_array[][COLS])
    {
        int row, col;
        for (row = 0; row < ROWS; row++)
        {
            for (col = 0; col < COLS; col++)
            {
                m_array[row][col] = 1;
            }
        }
    }

Y para llamar a esta función, podemos utilizar:
    set_value(multi);
Ahora, dentro de la función hemos utilizado los valores de ROWS y COLS definidos al principio con #define ROWS 5 y #define COLS 10 para establecer los límites de los bucles for. Para el compilador estas definiciones son constantes. Tanto row como col son variables locales. La definición formal de los parámetros permiten al compilador determinar las características del valor del puntero que será pasado en tiempo de ejecución. Realmente no necesitamos la primera dimensión, y como veremos después, hay momentos donde es preferible no definirlo dentro de la definición de parámetros (por hábito o por consistencia, yo no lo he utilizado aquí). Ahora, la segunda dimensión debe utilizarse como vemos en la expresión del parámetro. La razón es que lo necesitamos en la evaluación de m_array[row][col] como hemos visto. Como el parámetro define el tipo de dato (en este caso int), y las variables automáticas (row y col) se definen dentro de la función para los bucles for, con un único parámetro sólo puede pasarse un valor. En este caso, éste parámetro es el valor de multi como vemos en la llamada a la función, que es la dirección del primer elemento, a menudo también llamado como un puntero a un array. Por tanto, la única forma que tenemos de indicar la segunda dimensión al compilador es incluirlo explícitamente en la definición del parámetro.

De hecho, generalmente todas las dimensiones superiores a una son necesarias en arrays multidimensionales. Esto es: si hablamos de 3 dimensiones, la dimensión 2 y 3 deben especificarse en la definición de parámetros.

Continuar con el Tutorial de Punteros

Tabla de Contenidos