Dan*_*iel 1 c arrays struct multidimensional-array
我试图在C中编写一个程序,根据用户输入生成螺旋并将其打印到控制台.我无法弄清楚如何访问我在结构"螺旋"中定义的2D数组"数据".如何修复"警告:从不兼容的指针类型分配"错误?
#include <stdio.h>
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 < size; i++) {
data[0][i] = 1;
}
int currX = 0;
int currY = size - 1;
for (i = size - 1; i > 0; i -= 2) {
int j;
for (j = 0; j < 2; j++) {
int k;
switch (rotate()) {
case 0:
for (k = 0; k < i; k++) {
data[++currX][currY] = 1;
}
break;
case 1:
for (k = i; 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 < spiral.size; j++) {
switch (spiral.data[i][j]) {
case 0:
printf(" ");
break;
case 1:
printf("#");
break;
}
}
printf("\n");
}
}
static int rotate() {
static int val = 0;
int tmp = val;
val++;
if (val > 3)
val = 0;
return tmp;
}
Run Code Online (Sandbox Code Playgroud)
在generateSpiral函数中,您使结构指针指向局部变量data,但是当函数返回data超出范围时,指针现在指向未分配的内存,从而导致未定义的行为.
但是,这并不是唯一的问题:第二个问题是,指针的指针是不一样的数组的数组,存储器布局是不同的.
最后一部分,让我们看一个例子.让我们说我们有以下声明
int a[2][2];
Run Code Online (Sandbox Code Playgroud)
在内存中它看起来像这样:
+---------+---------+---------+---------+ | a[0][0] | a[0][1] | a[1][0] | a[1][1] | +---------+---------+---------+---------+
换句话说,所有数据都是连续的.
如果你,另一方面有一个声明像
int **p;
Run Code Online (Sandbox Code Playgroud)
并正确地为它分配数据,它看起来像
+------+------+-----+ | 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
// I.e. we allocate an "array" of pointers
data = malloc(size * sizeof(int *));
// Then allocate each entry in the above allocated "array"
// I.e. 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));
Run Code Online (Sandbox Code Playgroud)
现在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);
Run Code Online (Sandbox Code Playgroud)
关于指针,指针可以指向任何内存地址,并且实际上没有安全性或检查它指向有效位置.此外,C不会对值和结构进行深度复制,如果有指针并使其指向某处,则编译器或运行时系统不会复制.
关于范围界定,Java也有局部变量,就像C中函数返回那些超出范围一样.Java和C之间的区别在于,如果返回对本地对象的引用,那么只要存在对象的引用,Java就会跟踪它并将对象保留在内存中.C没有引用,指针只是一个整数,其值是内存中的地址,并且指向的数据不知道有指向它的指针或数量.
| 归档时间: |
|
| 查看次数: |
13429 次 |
| 最近记录: |