在Struct中存储和访问2D数组

我正在尝试在C中编写一个程序,根据用户输入生成螺旋并将其打印到控制台。 我无法弄清楚如何访问我在结构“螺旋”中定义的2D数组“数据”。 如何修复“警告:从不兼容的指针类型分配”错误?

#include  typedef struct Spiral { int size; int **data; } Spiral; Spiral generateSpiral(int size); void printSpiral(Spiral spiral); static int rotate(); int main() { int size; scanf("%d", &size); Spiral spiral = generateSpiral(size); printSpiral(spiral); return 0; } Spiral generateSpiral(int size) { int data[size][size]; int i; for (i = 0; i < size; i++) { int j; for (j = 0; j < size; j++) { data[i][j] = 0; } } for (i = 0; i  0; i -= 2) { int j; for (j = 0; j < 2; j++) { int k; switch (rotate()) { case 0: for (k = 0; k  0; k--) { data[currX][--currY] = 1; } break; case 2: for (k = i; k > 0; k--) { data[--currX][currY] = 1; } break; case 3: for (k = 0; k < i; k++) { data[currX][++currY] = 1; } break; } } } Spiral spiral; spiral.size = size; spiral.data = data; return spiral; } void printSpiral(Spiral spiral) { int i; for (i = 0; i < spiral.size; i++) { int j; for (j = 0; j  3) val = 0; return tmp; } 

generateSpiral函数中,您使结构指针指向局部变量data ,但是当函数返回data超出范围时,指针现在指向未分配的内存,从而导致未定义的行为

但这不是你唯一的问题:第二个问题是指向指针的指针与数组数组不同,内存布局不同。


最后一部分,让我们看一个例子。 让我们说我们有以下声明

 int a[2][2]; 

在内存中它看起来像这样:

 + --------- + --------- + --------- + --------- +
 |  a [0] [0] |  a [0] [1] |  a [1] [0] |  a [1] [1] |
 + --------- + --------- + --------- + --------- +

换句话说,所有数据都是连续的。

如果你,另一方面有一个声明像

 int **p; 

并正确地为它分配数据,它看起来像

 + ------ + ------ + ----- +
 |  p [0] |  p [1] |  ...... |
 + ------ + ------ + ----- +
   |  |  |
   |  |  v
   |  |  ...
   |  v
   |  + --------- + --------- + ----- +
   |  |  p [1] [0] |  p [1] [1] |  ...... |
   |  + --------- + --------- + ----- +
   v
   + --------- + --------- + ----- +
   |  p [0] [0] |  p [0] [1] |  ...... |
   + --------- + --------- + ----- +

记忆不再是连续的。 不再有任何最大大小,指针指向连续的内存区域,但无法知道该区域有多大。 你必须自己跟踪它。


这两个问题的简单解决方案是仅使用指针指针,然后动态分配堆:

 int **data; // First allocate memory for `size` number of pointers // Ie we allocate an "array" of pointers data = malloc(size * sizeof(int *)); // Then allocate each entry in the above allocated "array" // Ie make each pointer in the "array" point to an "array" of `int` for (int i = 0; i < size; ++i) data[i] = malloc(size * sizeof(int)); 

现在可以直接使用局部变量data来分配到spiral.data

但有一个问题:在Java中,您不必释放您分配的内存,它会自动处理。 在C中它不是自动处理的,你必须手动释放你分配的内存,否则你将有内存泄漏

释放内存可以像

 // First free all the "sub-arrays" for (int i = 0; i < size; ++i) free(spiral.data[i]); // Then free the top-level "array" free(spiral.data); 

关于指针,指针可以指向任何内存地址,并且实际上没有安全性或检查它指向有效位置。 此外,C不会对值和结构进行深度复制,如果有指针并使其指向某处,则编译器或运行时系统不会复制。

关于范围界定,Java也有局部变量,就像C中的函数返回那些超出范围一样。 Java和C之间的区别在于,如果返回对本地对象的引用,那么只要存在对象的引用,Java就会跟踪它并将对象保留在内存中。 C没有引用,指针只是一个整数,其值是内存中的地址,而指向的数据不知道有指向它的指针或数量。

您的问题是由于向量大小函数返回的int和unsigned int之间不匹配。 将int i,j更改为type_t,这样它们也是一个无符号整数,就像向量的大小一样。 这就是你收到警告的原因