Asignar a matriz 2D una matriz 2D en una estructura

Tengo una función que intenta recorrer una matriz 2D en una estructura:

typedef struct node { int grid[3][3]; } Node; void someFunction(Node *node) { int grid[3][3] = node->grid; //loop through } 

Cuando bash comstackr esto sin embargo obtengo un

mp.c: 42: error: inicializador inválido

No puede asignar arreglos en C. Simplemente no está permitido. Cuando escribiste:

 int grid[3][3] = node->grid; 

estaba intentando inicializar la matriz local, la grid , desde el node pasado. Si eso estuviera permitido (lo cual no es así), entonces no necesitarías un bucle después.

Sin embargo, puede asignar estructuras, incluso si contienen matrices, por lo que si la estructura local fuera un Node , podría haber escrito:

 Node local = *node; 

No sería necesario recorrer las matrices después para inicializar local .

Puede recorrer los arrays haciendo una copia de un elemento a la vez:

 for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) grid[i][j] = node->grid[i][j]; 

También puedes usar memmove() o memcpy() :

 int grid[3][3]; assert(sizeof(grid) == sizeof(node->grid)); memcpy(grid, node->grid, sizeof(grid)); 

En un momento, otra respuesta sugirió:

Cambia la línea:

 int grid[3][3] = node->grid; 

a:

 int **grid = node->grid; 

Noté que esto no funcionará, y fui legítimamente desafiado a explicar por qué. Eso requiere espacio y formato.

En primer lugar, las notas del comstackdor:

 warning: initialization from incompatible pointer type 

Eso está diciendo ‘estás jugando con fuego’.

Supongamos que ignoramos esa advertencia. La grid local ahora apunta a la esquina superior izquierda de la matriz (si ve matrices que crecen hacia abajo y de izquierda a derecha). El valor almacenado allí es un número simple, no un puntero inicializado, pero cuando el comstackdor evalúa la grid[0] , se obliga a asumir que producirá un puntero. Si node->grid[0][0] contiene un cero, es probable que obtenga una falla de segmentación y un volcado de núcleo para eliminar la referencia de un puntero nulo (en el supuesto de que los punteros y el int sean del mismo tamaño, lo que generalmente es cierto en 32- sistemas de bits), o algún otro comportamiento indefinido. Si node->grid[0][0] contiene otro valor, entonces el comportamiento aún no está definido, pero no es tan predecible.

Si no desea hacer la copia, solo desea un puntero a la matriz en la estructura (nota: si asigna valores a *pointer , se cambiará el contenido de la matriz en la estructura), puede lograr este objective en dos maneras:

 #include  typedef struct node { int grid[3][3]; } Node; void someFunction1(Node *node) { int i, j; int (*grid)[3] = node->grid; for(i=0; i<3; i++){ for(j=0; j<3; j++){ printf("%d ", grid[i][j]); } printf("\n"); } } void someFunction2(Node *node) { int i, j; int *grid = (int*) node->grid; for(i=0; i<3; i++){ for(j=0; j<3; j++){ printf("%d ", grid[i*3+j]); // i * column_number + j } printf("\n"); } } int main() { Node t; int i, *p; //initialization: t.grid[0][0]=0, ..., t.grid[2][2]=8 for(i=0, p=(int*)t.grid; i<9; p++, i++){ *p = i; } printf("Function1:\n"); someFunction1(&t); printf("Function2:\n"); someFunction2(&t); return 0; } 

El código anterior muestra una función simple para usar punteros. Todos son seguros y están a la altura.

Si desea usar puntero a puntero, int** , tendrá que hacerlo de una manera diferente, ya que los arreglos son almacenamiento lineal en la memoria (por lo que el código anterior puede usar un int* para apuntar al principio del arreglo). y operarlo), pero int** no.

EDITAR

Así que aquí viene el someFunction3()

 void someFunction3(Node *node) { int i, j; int **p; // 3 is the row number. Ignore checking malloc failure p = malloc(sizeof(int)*3); for(i=0; i<3; i++) { p[i] = (int*) node->grid[i]; //assign address of each row of array to *p } for(i=0; i<3; i++) { for(j=0; j<3; j++) { printf("%d ", p[i][j]); } printf("\n"); } free(p); } 

Vea este otro hilo para la misma pregunta y la respuesta que no implica copiar la memoria:

Crear un puntero a matriz bidimensional.