¿Es malo hacer referencia a los elementos de la matriz de acceso a través de la aritmética del puntero en lugar del operador []?

12

Recién comencé a aprender a programar en C, y para mejorar mi comprensión de los punteros y las matrices, intenté referirme a los elementos de una matriz sin crear ningún puntero:

for(k1 = 0; k1 < ROW; k1++){
    for(k2 = 0; k2 < COLUMN; k2++){

        array[k1][k2] = k1*COLUMN + k2 + 1;

        printf("[%d][%d] = %d\n", k1, k2, *(array[k1] + k2));

    }
}

Todo el código se compila y se ejecuta sin problemas.

Me imagino que tener que crear un puntero para cada matriz en un gran código fuente parece ser muy ineficiente.

Entonces, en lugar de tener la dirección de una matriz almacenada y recuperada usando un puntero, ¿es una mala práctica de programación usar la dirección de la matriz directamente, como se muestra arriba?

Niko Gambt
fuente
El uso printf "[%d][%d] = %d\n", k1, k2, array[k1] [k2]));evitaría el puntero aritmético y es más fácil de entender.
Kasper van den Berg
1
Jaja, me tienes. Lo hice solo como un experimento para comprender mejor cómo funcionan los punteros y las matrices.
Niko Gambt
La aritmética del puntero es en realidad un 30% más rápida que el uso de índices de matriz.
Andy

Respuestas:

16

Es "malo" solo en la medida en que sea menos legible. a[x]es lo mismo que *(a+x), así que no hay diferencia en eficiencia o comportamiento (de hecho, x[a]también funcionará). Es solo que a[x]generalmente es mucho más intuitivo para nosotros los humanos.

Pero eso no quiere decir que la legibilidad no sea un gran problema. Para ver qué tan grande, piense cómo "leería" estas dos expresiones si las viera en código:

  • *(a+x)= "La cosita señalada por la suma del puntero ay el entero x"
  • a[x]= "El xmiembro th de la matriz a"

Del mismo modo, cuando necesita hacer referencia a la dirección de un elemento de matriz:

  • (a+x)= "La suma del puntero ay el entero x"
  • &a[x]= "La dirección del xmiembro th de la matriz a"

La mayoría de las veces, las []versiones son más fáciles de entender cuando se busca código no trivial que opera en varias matrices diferentes (especialmente matrices de matrices). Es por eso que el []operador existe en primer lugar.

PD: Hacer este tipo de cosas estrictamente como un ejercicio de aprendizaje es una muy buena idea. Es importante comprender que las matrices realmente son solo punteros y compensaciones.

Ixrec
fuente
Esta. Gracias. Me acabo de dar cuenta de que lo que realmente quiero saber es si es necesario o no referirse a la dirección de cualquier elemento de la matriz, y luego a la dirección de otro elemento, y luego otro, ¿sigue siendo malo? ¿NO usar un puntero y, en cambio, usar la matriz directamente como lo hice? Esta pregunta mía ha sido realmente difícil de precisar, es por eso que no la escribí en el OP. De todos modos, como no lo pregunté, su respuesta es satisfactoria.
Niko Gambt
1
@NikoGambt Siempre puedes hacer otra pregunta =)
Ixrec
1
¿Qué quieres decir solo en la medida en que ...? El objetivo de los lenguajes de programación es hacer que el código sea más fácil de leer para los humanos. Si no nos importara eso, todos estaríamos escribiendo códigos de operación en hexadecimal.
Solomon Slow
2
Las matrices no son punteros, la simple decadencia de los punteros implícitamente.
CodesInChaos
4

Sí, es una mala práctica, pero no por razones de ineficiencia.

El operador de matriz utiliza un puntero aritmético debajo del capó, por lo que son igualmente eficientes.

El problema con el puntero aritmétrico es que es muy propenso a errores y es más difícil de leer.

Regla general: no utilice el puntero aritmétrico a menos que sea necesario.

usuario694733
fuente
1
Dado que de todos modos utiliza la aritmética de punteros, ¿no significa eso que los punteros también son igualmente propensos a errores y difíciles de leer?
Niko Gambt
1
Los compiladores de @NikoGambt son bastante buenos para hacer aritmética de punteros bajo el capó y rara vez cometerán 'errores'; son los programadores quienes cometerán errores con errores desagradables como consecuencia.
Kasper van den Berg
@KaspervandenBerg Sí, estoy de acuerdo. Sin embargo, estoy interesado en los errores cometidos por los programadores, y no estoy muy seguro de si es una mala práctica de programación hacer lo que hice anteriormente, en los casos en que sea necesario referirse a la dirección de una matriz , si tales casos existen.
Niko Gambt
1
@NikoGambt Escribir algo que sea menos legible para fines de rendimiento es casi siempre una mala práctica, pero escribir algo que sea menos legible sin ganancia es una práctica inequívocamente mala.
Neil
@Neil Mi pequeño experimento no tiene sentido. Al hacerlo, aprendí que el compilador parece hacer una matriz de punteros para referirse a una matriz multidimensional. Sin embargo, dado que usted dijo que la legibilidad es más importante que el rendimiento, supongo que sigue siendo una mala práctica de programación.
Niko Gambt
0

Refresque su aprendizaje c, acaba de descubrir uno de los trabalenguas pequeños. No está haciendo aritmética de puntero en una matriz, sino una matriz de punteros. No es posible hacer aritmética de puntero en matrices. Una matriz se descompone en un puntero, pero no es un puntero del tipo en sí mismo. Lo que tienes (ver comentario de cmaster) es

int *array[]; //This is a array to pointers of type *int. 

array[k1] + k2; //This is pointer arithmetic on one pointer stored in the array  

Anular la referencia a este puntero le da el valor al que apunta su puntero recién calculado. Generalmente no tiene sentido hacer lo que estás haciendo. Pero puede linealizar la matriz y luego una zancada, como esta.

int array[y_dim*x_dim]; 
int index = x_dim*y + x; 
array[index]; //Gives you the element in x, y!

Stride her is x_dim. ¡Espero que mi respuesta sea aclaradora!

fhtuft
fuente
Desde el OP no está claro si usa un int* array[ROW];an int array[ROW][COLUMN];o un an int (*array)[COLUMN];. Cualquiera de estas tres definiciones se puede usar con el código en el OP.
cmaster - reinstalar a monica el
Sí, soy consciente de eso, mi respuesta es un poco torpe en ese punto. Lo corrijo, gracias!
fhtuft