简体   繁体   English

将结构中的二维数组分配给二维数组

[英]Assign to 2D array a 2D array in a struct

I have a function which tries to loop through a 2D array in a struct:我有一个 function 试图循环遍历结构中的二维数组:

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 mp.c:42:错误:初始化程序无效

You cannot assign arrays in C.您不能在 C 中分配 arrays。 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 .您试图从传入的node初始化本地数组grid 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:但是,您可以分配结构,即使它们包含 arrays,因此如果本地结构是Node ,您可以编写:

Node local = *node;

You would not need to loop through the arrays afterwards to initialize local .之后,您无需遍历 arrays 即可初始化local

You can loop through the arrays, doing the copy one element at a time:您可以遍历 arrays,一次复制一个元素:

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() :您还可以使用memmove()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).本地grid现在指向阵列的左上角(如果您看到 arrays 从左到右向下并穿过)。 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.存储在那里的值是一个普通数字,而不是一个初始化的指针,但是当编译器评估grid[0]时,它被迫假设会产生一个指针。 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.如果node->grid[0][0]包含零,您可能会因为取消引用 null 指针而获得分段错误和核心转储(假设指针和int大小相同,这通常在 32-位系统),或其他一些未定义的行为。 If node->grid[0][0] contains another value, then the behaviour is still undefined, but not quite as predictable.如果node->grid[0][0]包含另一个值,那么行为仍然是未定义的,但不是完全可预测的。

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:如果你不想做拷贝,只需要一个指向结构体中数组的指针(注意:如果你给*pointer赋值,结构体中数组的内容会改变),你可以达到这个目的有两种方式:

#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.上面的代码显示了一个简单的 function 使用指针。 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.如果要使用指向指针int**的指针,则必须以不同的方式进行,因为 arrays 是 memory 中的线性存储(因此上面的代码可以使用int*指向数组的开头并操作它),但int**不是。

EDIT编辑

So here comes the someFunction3()所以这里出现了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:请参阅此其他线程以获取相同的问题以及不涉及复制 memory 的答案:

Create a pointer to two-dimensional array 创建指向二维数组的指针

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM