在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,这样它们也是一个无符号整数,就像向量的大小一样。 这就是你收到警告的原因