我有试图通过一个结构体的二维数组循环功能:分配到二维数组二维数组中的一个结构
typedef struct node
{
int grid[3][3];
} Node;
void someFunction(Node *node) {
int grid[3][3] = node->grid;
//loop through
}
当我尝试编译这个,但是我得到一个
mp.c:42: error: invalid initializer
我有试图通过一个结构体的二维数组循环功能:分配到二维数组二维数组中的一个结构
typedef struct node
{
int grid[3][3];
} Node;
void someFunction(Node *node) {
int grid[3][3] = node->grid;
//loop through
}
当我尝试编译这个,但是我得到一个
mp.c:42: error: invalid initializer
你不能在C中分配数组,这是不允许的。当你写:
int grid[3][3] = node->grid;
您试图初始化本地阵列,grid
,从传递node
。如果这是允许的(事实并非如此),那么你以后不需要循环。
您可以分配结构,不过,即使它们包含数组,因此,如果局部结构是一个Node
,你可以写:
Node local = *node;
您将无法通过阵列需要循环之后初始化local
。
你可以通过数组循环,拷贝一个元素在同一时间做:
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
grid[i][j] = node->grid[i][j];
您还可以使用memmove()
或memcpy()
:
int grid[3][3];
assert(sizeof(grid) == sizeof(node->grid));
memcpy(grid, node->grid, sizeof(grid));
在同一时间,另一答案建议:
Change the line:
int grid[3][3] = node->grid;
to:
int **grid = node->grid;
我注意到这不起作用 - 并且被合理地解释了原因。这需要空间和格式。
首先,编译器注意事项:
warning: initialization from incompatible pointer type
即说“你是在玩火”。
假设我们忽略该警告。当地的grid
现在指向数组的左上角(如果您看到阵列从左向右逐渐增大)。存储在那里的值是一个普通数字,不是初始化的指针,但是当编译器评估grid[0]
时,它被迫假设会产生一个指针。如果node->grid[0][0]
包含0,那么您可能会得到一个分段错误和核心转储来取消引用空指针(假设指针和int
的大小相同,在32位系统上通常是这样),或者其他未定义的行为。如果node->grid[0][0]
包含另一个值,那么行为仍然是未定义的,但不是很可预测。
,然后我可以像正常的二维数组一样循环网格? – Jeune
@Jeune:是的,它只是一个初始化数组,其中有一个其他内容的副本,您可以在任何您认为有必要的地方操作该数组。无论使用哪种(可编译)机制来初始化本地数组,这都可以工作。 –
请注意,您将在此处制作数组的副本,而不仅仅是使用结构中已有的数组。这可能是你想要的,但是如果你只是想要一个局部变量指向结构中的同一个数组,请参见下面的答案。 –
看到这个其他线程对同一问题,答案,不涉及复制内存:
否;这将无法正常工作。为了工作,'grid [0]','grid [1]'和'grid [2]'每个都必须是一个指向数组的指针,尽管出现了,但它不是。 'node-> grid'中的地址被分配给'grid',但'grid [1]'没有被正确地初始化。答案很难解释这一点;在评论中这完全是不重要的。 –
为什么它不工作? –
虽然我得到这个警告:mp.c:42:警告:从不兼容的指针类型初始化那是什么意思? – Jeune
如果你不想做的拷贝,只想要一个指针阵列中的结构(注意:如果分配值*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;
}
上面的代码显示一个简单的函数使用指针。他们都是安全的,达到标准。
如果要使用指针指针int**
,则必须以不同的方式创建它,因为数组是线性存储器(因此上述代码可以使用指向开头的int*
数组并操作它),但不是int**
。
编辑
所以来这里的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);
}
一件事,为什么不只是传递一个int [] [3],而不是在一个节点包裹它,因为它只是一个1名成员结构? –
@Jesus Ramos我打算在结构中加入其他属性。 – Jeune
@Jesus Ramos:尽管Jeune表示它不会那样,但将数组变成“头等”类型是一种常见的方式。简单地说,就是为了带来诸如允许赋值(自动复制数组)或从函数返回数组等优点。 – sidyll