Aritmética de punteros multidimensionales en C/C++

En C/C++, las arrays y los punteros tienen una semántica similar, excepto en la información de tipo.

Como ejemplo, dada una array 3D

int buffer[5][7][6];

Se puede acceder a un elemento en la ubicación [2][1][2] como “ buffer[2][1][2] ” o  *( *( *(buffer + 2) + 1) + 2) .

Tenga en cuenta la siguiente declaración

T *p; // p is a pointer to an object of type T

Cuando un puntero p apunta a un objeto de tipo T, la expresión *p es de tipo T. Por ejemplo , el búfer  es de tipo array de 5 arrays bidimensionales. El tipo de expresión *buffer es “array de arrays (es decir, array bidimensional)”.

Basado en el concepto anterior, traducir la expresión *( *( *(búfer + 2) + 1) + 2)  paso a paso lo hace más claro.

  1. buffer – Una array de 5 arrays bidimensionales, es decir, su tipo es “array de 5 arrays bidimensionales”.
  2. búfer + 2 : desplazamiento para el tercer elemento en la array de 5 arrays bidimensionales.
  3. *(búfer + 2) – desreferenciado, es decir, su tipo ahora es una array bidimensional.
  4. *(buffer + 2) + 1 – desplazamiento para acceder al segundo elemento en la array de 7 arrays unidimensionales.
  5. *( *(buffer + 2) + 1) – desreferenciar (acceder), ahora el tipo de expresión “ *( *(buffer + 2) + 1) ” es una array de enteros.
  6. *( *(buffer + 2) + 1) + 2 – desplazamiento para obtener el elemento en la tercera posición en la array de enteros de una sola dimensión.
  7. *( *( *(buffer + 2) + 1) + 2) – accediendo al elemento en la 3ra posición (el tipo de expresión general ahora es int ).

El compilador calcula un «desplazamiento» para acceder al elemento de la array. El «desplazamiento» se calcula en función de las dimensiones de la array. En el caso anterior, desplazamiento = 2 *() + 1 *() + 2 . Los que están en color son dimensiones, tenga en cuenta que la dimensión más alta no se utiliza en el cálculo de compensación . Durante el tiempo de compilación, el compilador conoce las dimensiones de la array. Usando offset podemos acceder al elemento como se muestra a continuación,

element_data = *( (int *)buffer + offset );

No siempre es posible declarar las dimensiones de la array en tiempo de compilación. A veces necesitamos interpretar un búfer como un objeto de array multidimensional. Por ejemplo, cuando estamos procesando una imagen 3D cuyas dimensiones se determinan en tiempo de ejecución, no se pueden usar las reglas habituales de subíndice de array. Se debe a la falta de dimensiones fijas durante el tiempo de compilación. Considere el siguiente ejemplo,

int *base;

Donde la base apunta a un búfer de imagen grande que representa una imagen 3D de dimensión lxbxh donde l, b y h son variables. Si queremos acceder a un elemento en la ubicación (2, 3, 4) necesitamos calcular el desplazamiento del elemento como

offset = 2 * (bxh) + 3 * (h) + 4 y el elemento ubicado en base + offset .

Generalizando aún más, dada la dirección de inicio (por ejemplo , base ) de una array de dimensiones de tamaño [ lxbxh ], podemos acceder al elemento en una ubicación arbitraria ( a, b, c ) de la siguiente manera,

datos = *(base + a * ( bxh ) + b * ( h ) + c); // Tenga en cuenta que no hemos utilizado la dimensión superior l .

El mismo concepto se puede aplicar a cualquier número de dimensiones. No necesitamos la dimensión superior para calcular el desplazamiento de ningún elemento en la array multidimensional. Es la razón detrás de omitir la dimensión superior cuando pasamos arrays multidimensionales a funciones . La dimensión superior es necesaria solo cuando el programador itera sobre un número limitado de elementos de dimensión superior.

Rompecabezas AC/C++, predecir el resultado del siguiente programa

int main()
{
    char arr[5][7][6];
    char (*p)[5][7][6] = &arr;
  
    /* Hint: &arr - is of type const pointer to an array of
       5 two dimensional arrays of size [7][6] */
  
    printf("%d\n", (&arr + 1) - &arr);
    printf("%d\n", (char *)(&arr + 1) - (char *)&arr);
    printf("%d\n", (unsigned)(arr + 1) - (unsigned)arr);
    printf("%d\n", (unsigned)(p + 1) - (unsigned)p);
  
    return 0;
}

Producción:

1

210

42

210

Gracias al estudiante  por señalar un error.

—  Venki . Escriba comentarios si encuentra algo incorrecto o si desea compartir más información sobre el tema tratado anteriormente.

Publicación traducida automáticamente

Artículo escrito por GeeksforGeeks-1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *