Assign to 2D array a 2D array in a struct
I have a开发者_JAVA百科 function which tries to loop through a 2D array in a struct:
typedef struct node
{
int grid[3][3];
} Node;
void someFunction(Node *node) {
int grid[3][3] = node->grid;
//loop through
}
When I try to compile this however I get a
mp.c:42: error: invalid initializer
You cannot assign arrays in C. It is simply not allowed. When you wrote:
int grid[3][3] = node->grid;
you were attempting to initialize the local array, grid
, from the passed in node
. If that were permitted (which it isn't), then you'd not need a loop afterwards.
You can assign structures, though, even if they contain arrays, so if the local structure were a Node
, you could have written:
Node local = *node;
You would not need to loop through the arrays afterwards to initialize local
.
You can loop through the arrays, doing the copy one element at a time:
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
grid[i][j] = node->grid[i][j];
You can also use memmove()
or memcpy()
:
int grid[3][3];
assert(sizeof(grid) == sizeof(node->grid));
memcpy(grid, node->grid, sizeof(grid));
At one time, another answer suggested:
Change the line:
int grid[3][3] = node->grid;
to:
int **grid = node->grid;
I noted that this will not work - and was legitimately challenged to explain why. That requires space and formatting.
First of all, the compiler notes:
warning: initialization from incompatible pointer type
That is saying 'you are playing with fire'.
Let's suppose we ignore that warning. The local grid
now points at the top-left corner of the array (if you see arrays growing down and across from left-to-right). The value stored there is a plain number, not an initialized pointer, but when the compiler evaluates grid[0]
, it is forced to assume that will produce a pointer. If node->grid[0][0]
contains a zero, you will probably get a segmentation fault and core dump for dereferencing a null pointer (on the assumption that pointers and int
are the same size, which is generally true on 32-bit systems), or some other undefined behaviour. If node->grid[0][0]
contains another value, then the behaviour is still undefined, but not quite as predictable.
If you don't want to do the copy, just want a pointer to the array in the struct (note: if you assign values to *pointer
, the content of the array in the struct will be changed), you can achieve this aim in two ways:
#include <stdio.h>
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;
}
The above code shows a simple function to use pointers. They are all safe and up to standard.
If you want to use pointer to pointer, int**
, you will have to make it in a different way, because, arrays are linear storage in memory (so the above code can use an int*
to point to the beginning of the array and operate it), but int**
not.
EDIT
So here comes the 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);
}
See this other thread for the same question and the answer that doesn't involve copying the memory:
Create a pointer to two-dimensional array
精彩评论