Matriz a decaimiento de puntero y pasando matrices multidimensionales a funciones

Sé que una matriz se descompone en un puntero, de modo que si uno declara

char things[8]; 

y luego usa things en otro lugar, things es un puntero al primer elemento de la matriz.

Además, desde mi entender, si uno declara

 char moreThings[8][8]; 

luego, más moreThings no es de tipo puntero a char, sino de tipo “matriz de punteros a char”, porque el decaimiento solo se produce una vez.

Cuando se pasan más moreThings a una función (digamos con prototype void doThings(char thingsGoHere[8][8]) ¿qué está pasando realmente con la stack?

Si moreThings no es de tipo puntero, ¿sigue siendo realmente una referencia moreThings ? Creo que siempre pensé que aún más moreThings representaban la dirección base de la matriz multidimensional. ¿Qué doThings si doThings tomara doThings entrada de thingsGoHere y las pasara a otra función?

¿La regla es más o menos que a menos que uno especifique una entrada de matriz como const entonces la matriz siempre será modificable?

Sé que las cosas de verificación de tipos solo ocurren en tiempo de comstackción, pero todavía estoy confundido acerca de lo que técnicamente cuenta como un pase por referencia (es decir, solo cuando se pasan argumentos de tipo puntero, o una serie de punteros sería un pase). por referencia también?)

Lamento estar un poco por todos lados con esta pregunta, pero debido a mi dificultad para entender esto, es difícil articular una investigación precisa.

Lo tienes un poco mal: moreThings también se descompone en un puntero al primer elemento, pero como es una matriz de una serie de caracteres, el primer elemento es una “matriz de 8 caracteres”. Entonces, el puntero decaído es de este tipo:

 char (*p)[8] = moreThings; 

El valor del puntero es, por supuesto, el mismo que el valor de &moreThings[0][0] , es decir, del primer elemento del primer elemento, y también el mismo de &a , pero el tipo es diferente en cada caso.

Aquí hay un ejemplo si char a[N][3] :

 +===========================+===========================+==== |+--------+--------+-------+|+--------+--------+-------+| || a[0,0] | a[0,1] | a[0,2]

a[1,0] | a[1,1] | a[1,2]|| … |+——–+——–+——-+++——–+——–+——-++ … | a[0] | a[1] | +===========================+===========================+==== a ^^^ ||+– &a[0,0] |+—–&a[0] +——-&a

  • &a : dirección de toda la matriz de matrices de caracteres, que es un char[N][3]

  • &a[0] , lo mismo que a : dirección del primer elemento, que a su vez es un char[3]

  • &a[0][0] : dirección del primer elemento del primer elemento, que es un char

Esto demuestra que diferentes objetos pueden tener la misma dirección, pero si dos objetos tienen la misma dirección y el mismo tipo, entonces son el mismo objeto.

“DIRECCIÓN ARRAY Y PUNTORES PARA ARRAYS MULTIDIMENSIONALES”

Permite comenzar con una matriz 1-D primero:

  • Declaración char a[8]; crea una matriz de 8 elementos.
    Y aquí a dirección es del primer elemento pero no la dirección de la matriz .

  • char* ptr = a; es la expresión correcta ya que ptr es un puntero a char y puede abordar el primer elemento.

  • ¡Pero la expresión ptr = &a está equivocada ! Porque ptr no puede abordar una matriz.

  • & a significa dirección del conjunto. Realmente el valor de a y &a son iguales pero, semánticamente, ambos son diferentes, uno es la dirección de char, otro es la dirección del conjunto de 8 caracteres.

  • char (*ptr2)[8]; Aquí ptr2 is pointer to an array of 8 chars , y esta vez ptr2=&a es una expresión válida.

  • El tipo de datos de &a es char(*)[8] y el tipo de a es char[8] que simplemente decae en char* en la mayoría de las operaciones, por ejemplo, char* ptr = a;

    Para entender mejor leer: ¿ Diferencia entre char *str y char str[] y cómo ambas tiendas en la memoria?

Segundo caso,

  • Declaración char aa[8][8]; crea una matriz 2-D de tamaño 8x8 .

  • Cualquier matriz 2-D también se puede ver como una matriz 1-D en la que cada elemento de la matriz es una matriz 1-D .

  • aa es la dirección del primer elemento que es una matriz de 8 caracteres. La expresión ptr2 = aa es válida y correcta.

  • Si declaramos lo siguiente:

     char (*ptr3)[8][8]; char ptr3 = &aa; //is a correct expression 

    Similar,
    moreThings en su statement char moreThings[8][8]; contiene la dirección del elemento puño que es una matriz de 8 elementos.

    Para entender mejor leer: ¿ Diferencia entre char* str[] y char str[][] y cómo ambas tiendas en la memoria?


Sería interesante saber:

  • morething es una dirección de 8 char array.

  • *morething es una dirección del primer elemento que es &morething[0][0] .

  • &morething es una dirección de matriz 2-D de 8 x 8.

    Y los valores de las direcciones de los tres anteriores son los mismos, pero semánticamente son todos diferentes.

  • **morething es el valor del primer elemento que es más morething[0][0] .

    Para entender mejor leer: ¿ Diferencia entre &str y str , cuando str se declara como char str[10] ?

Además,

  • void doThings(char thingsGoHere[8][8]) no es nada más que doThings(char (*thingsGoHere)[8]) y por lo tanto acepta cualquier matriz que sea bidimensional siendo la segunda dimensión 8.

Sobre el tipo de variables en C y C ++: (Me gustaría agregar en la respuesta)

  • Nada pasa por referencia en C su concepto de C ++. Si se usa en C, significa autor hablando de variable de puntero.
  • C admite pass by Address y pass by value .
  • C ++ admite Pass by address , pass by value y pass by Reference .

    Lectura: variables de puntero y variables de referencia

Al final,

  • El nombre de una matriz es un identificador constante no variable.

Bien explicado por Kerrek,

Además de eso, podemos probarlo con el siguiente ejemplo:

 #include  int main () { int a[10][10]; printf (".. %p %p\n", &a, &a+1); printf (".. %p %p \n ", &a[0], &a[0]+1); printf (".. %p %p \n ", &a[0][0], &a[0][0] +1); } 

La salida es:

 .. 0x7fff6ae2ca5c 0x7fff6ae2cbec = 400 bytes difference .. 0x7fff6ae2ca5c 0x7fff6ae2ca84 = 40 bytes difference .. 0x7fff6ae2ca5c 0x7fff6ae2ca60 = 4 bytes difference. 

& a +1 -> Mueve el puntero agregando el tamaño de la matriz completa. es decir: 400 bytes

& a [0] + 1 -> Mueve el puntero agregando el tamaño de la columna. es decir: 40 bytes.

& a [0] [0] +1 -> Mueve el puntero agregando el tamaño del elemento, es decir: 4 bytes.

[int tamaño es 4 bytes]

Espero que esto ayude. 🙂