简体   繁体   English

在结构中存储和访问2D阵列

[英]Storing and Accessing a 2D Array in a Struct

I am trying to code a program in C that generates a spiral based on user input and prints it to the console. 我正在尝试用C编写一个程序,该程序会根据用户输入生成螺旋形并将其打印到控制台。 I cannot figure out how to access the 2D array "data" that I defined in the struct "Spiral". 我无法弄清楚如何访问在结构“ Spiral”中定义的2D数组“数据”。 How do I fix the "warning: assignment from incompatible pointer type" error? 如何解决“警告:来自不兼容指针类型的分配”错误?

#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;
}

In the generateSpiral function you make the structures pointer point to the local variable data , but when the function returns data goes out of scope so the pointer now points to unallocated memory leading to undefined behavior . generateSpiral函数中,使结构指针指向局部变量data ,但是当函数返回data时,其范围超出范围,因此指针现在指向未分配的内存,从而导致未定义的行为

But that's not your only problem: A second problem is that a pointer to a pointer is not the same as an array of arrays, the memory layout is different. 但是,这并不是唯一的问题:第二个问题是,指针的指针是一样的数组的数组,存储器布局是不同的。


For the last part, lets check an example. 对于最后一部分,我们来看一个例子。 Lets say we have the following declaration 可以说我们有以下声明

int a[2][2];

In memory it will look something like this: 在内存中它将看起来像这样:

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

In other words, all data is contiguous. 换句话说,所有数据都是连续的。

If you, on the other hand have a declaration like 另一方面,如果您有一个声明,例如

int **p;

and allocate data for it correctly, it will look something like 并为其正确分配数据,它看起来像

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

The memory is no longer contiguous. 内存不再连续。 There is no longer any maximum size, a pointer points to a contiguous area of memory, but there is no way of knowing how big that area is. 不再有最大大小,指针指向内存的连续区域,但是无法知道该区域的大小。 You have to keep track of it yourself. 您必须自己跟踪它。


The simple solution to both the problems is to use only pointer to pointer, and then allocate dynamically of the heap: 解决这两个问题的简单方法是仅使用指向指针的指针,然后动态分配堆:

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));

Now the local variable data can be used directly to assign to spiral.data . 现在,可以将本地变量data直接用于分配给spiral.data

But there is a catch: In Java you don't have to free memory you allocate, it's handled automatically. 但是有一个陷阱:在Java中,您不必释放分配的内存,而是自动处理的。 In C it's not handled automatically, you have to manually free the memory you allocate or you will have a memory leak . 在C语言中,它不是自动处理的,您必须手动释放分配的内存,否则会发生内存泄漏

Freeing the memory can be done like 释放内存可以像

// 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);

Regarding pointers, a pointer can point to any memory address, and there is really no safety or checking that it points to a valid location. 关于指针,指针可以指向任何内存地址,并且实际上没有安全性或没有检查它是否指向有效位置。 Also, C does not do deep copying of values and structures, if you have a pointer and make it point somewhere, then the compiler or runtime system doesn't make a copy. 另外,C不会对值和结构进行深层复制,如果您有一个指针并将其指向某处,则编译器或运行时系统不会进行复制。

And about scoping, Java has local variables as well, and just like in C when a function returns those go out of scope. 关于作用域,Java也具有局部变量,就像在C中,当函数返回超出范围的局部变量一样。 The difference between Java and C, is that if you return a reference to a local object, then Java keeps track of that and keep the object in memory as long as there are references to the object. Java和C之间的区别在于,如果您返回对本地对象的引用,则Java会跟踪该对象并将该对象保留在内存中,只要存在对该对象的引用即可。 C doesn't have references, a pointer is just an integer whose value is an address in memory, and the data pointed to have no idea that there are pointers to it or how many. C没有引用,指针只是一个整数,其值是内存中的地址,并且所指向的数据不知道有指向它的指针或指向它的指针。

Your problem is due to a mismatch between the int and the unsigned int returned by the vectors size function. 您的问题是由于vectors函数返回的int与unsigned int之间不匹配。 Change your int i , j to type size_t so they are also an unsigned integer like the size of the vectors. 将in i,j更改为size_t,以便它们也像矢量的大小一样是无符号整数。 This is why you are getting the warning 这就是为什么您收到警告

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

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