存储和在结构访问一个二维数组 [英] Storing and Accessing a 2D Array in a Struct

查看:118
本文介绍了存储和在结构访问一个二维数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图code在C程序,根据用户的输入,并将其打印到控制台产生一个恶性循环。我无法弄清楚如何访问二维数组的数据,我在结构中螺旋中定义。我该如何解决?警告:从兼容的指针类型赋值错误

 的#include<&stdio.h中GT;typedef结构{螺旋
    INT大小;
    INT **数据;
}螺旋;螺旋generateSpiral(INT大小);
无效printSpiral(螺旋管);
静态INT旋转();诠释主(){
    INT大小;
    scanf函数(%d个,&安培;大小);
    螺旋管= generateSpiral(大小);
    printSpiral(螺旋);
    返回0;
}螺旋generateSpiral(INT大小){
    int数据[大小] [SIZE]
    INT I;
    对于(i = 0; I<大小;我++){
        诠释J;
        为(J = 0; J<大小; J ++){
            数据[I] [J] = 0;
        }
    }    对于(i = 0; I<大小;我++){
        数据[0] [I] = 1;
    }    INT currX = 0;
    INT咖喱=大小 - 1;    为(ⅰ=大小 - 1; I&大于0; I - = 2){
        诠释J;
        为(J = 0; J&2; J ++){
            时int k;
            开关(旋转()){
                情况下0:
                    对于(K = 0; K<我; k ++){
                        数据[++ currX] [咖喱] = 1;
                    }
                    打破;
                情况1:
                    为(K = 1; K&大于0; K--){
                        数据[currX] [ - 库里] = 1;
                    }
                    打破;
                案例2:
                    为(K = 1; K&大于0; K--){
                        数据[ - currX] [咖喱] = 1;
                    }
                    打破;
                案例3:
                    对于(K = 0; K<我; k ++){
                        数据[currX] [++库里] = 1;
                    }
                    打破;
            }
        }
    }
    螺旋管;
    spiral.size =大小;
    spiral.data =数据;
    返回螺旋;
}无效printSpiral(螺旋管){
    INT I;
    对于(i = 0; I< spiral.size;我++){
        诠释J;
        为(J = 0; J< spiral.size; J ++){
            开关(spiral.data [I] [J]){
                情况下0:
                    的printf();
                    打破;
                情况1:
                    的printf(#);
                    打破;
            }
        }
        的printf(\\ n);
    }
}静态INT旋转(){
    静态INT VAL = 0;
    INT TMP = VAL;
    VAL ++;
    如果(VAL→3)
        VAL = 0;
    返回TMP;
}


解决方案

generateSpiral 功能,您结构指针指向局部变量数据,但是当函数返回数据超出范围,所以,指针现在指向未分配的内存导致的 未定义行为

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


有关的最后部分,让检查的例子。比方说,我们有以下声明

  int类型的[2] [2];

在内存中它看起来是这样的:


+ --------- + --------- + --------- + --------- +
|一个[0] [0] |一个[0] [1] |一个[1] [0] |一个[1] [1] |
+ --------- + --------- + --------- + --------- +

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

如果你在另一方面有这样一个声明

  INT ** P;

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


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

的存储器不再是连续的。不再有任何的最大尺寸,指针指向一个连续的内存区域,但没有办法知道那个区域有多大的方式。你要跟踪它自己。


的简单的解决方案都存在的问题是仅使用指针的指针,然后动态地分配的堆:

  INT **数据;//首先分配内存`指针size`数
//即我们分配一个指针数组
数据=的malloc(大小* sizeof的为(int *));//然后分配上面分配的阵中的每个条目
//即使在阵列点的每个指针,指向一个`int`的数组
的for(int i = 0; I<大小; ++ I)
    数据[I] =的malloc(大小*的sizeof(INT));

现在局部变量数据可直接用于分配到 spiral.data

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

释放内存可以像

完成

  //首先释放所有的子阵
的for(int i = 0; I<大小; ++ I)
    免费(spiral.data [I]);//然后释放顶层阵列
免费(spiral.data);


关于指针,指针可以指向任何内存地址,实在是没有安全或检查它指向一个有效的位置。此外,C不做价值观和结构的深度复制,如果你有一个指针,它指向的地方,那么编译器或运行时系统不进行复印。

和有关作用域,Java有局部变量,以及,就像在C当函数返回那些走出去的范围。 Java和C之间的区别是,如果返回一个参考到本地对象,那么Java跟踪那,并保持在存储器中的对象,只要有对对象的引用。 C没有引用一个指针仅仅是一个整数,其值是在存储器中的地址,并将数据指出不知道有指针,或多少

I am trying to code a program in C that generates a spiral based on user input and prints it to the console. I cannot figure out how to access the 2D array "data" that I defined in the struct "Spiral". 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.

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.

But there is a catch: In Java you don't have to free memory you allocate, it's handled automatically. In C it's not handled automatically, you have to manually free the memory you allocate or you will have a memory leak.

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.

And about scoping, Java has local variables as well, and just like in C when a function returns those go out of scope. 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. 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.

这篇关于存储和在结构访问一个二维数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆