Allocating a 2D array of structures.

huangapple go评论59阅读模式
英文:

Allocating a 2D array of structures

问题

我想分配一个二维数组,其元素是我的自定义类型 "cell" 的结构体。但是,我做错了什么,看看我的代码。你能告诉我我的错误在哪吗?

#include <stdio.h>
#include <stdlib.h>

typedef struct
{
  int variable_1;
  int variable_2;
  int variable_3;
} cell;

void initialiseArray(unsigned long rows, unsigned long columns, cell array[rows][columns])
{
  for (int i = 0; i < rows; i = i + 1)
    for (int j = 0; j < columns; j = j + 1)
    {
      array[i][j].variable_1 = 0;
      array[i][j].variable_2 = 0;
      array[i][j].variable_3 = 0;
    }
}

int main()
{
  unsigned long rows = 200;
  unsigned long columns = 250;
  cell* array[rows];
  for (unsigned long i = 0; i < rows; i = i + 1)
    array[i] = malloc(columns * sizeof(cell));

  if (array == NULL)
  {
    printf("Error in \"main\": Memory could not be allocated.\n");
    return 3;
  }

  initialiseArray(rows, columns, array);

  return 0;
}
英文:

I want to allocate a 2D array of my custom type "cell", which is a structure. However, I am doing something wrong, see my code below. Could you please tell me where my mistake is?

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;

typedef struct
{
  int variable_1;
  int variable_2;
  int variable_3;
} cell;


void initialiseArray(unsigned long rows, unsigned long columns, cell array[rows][columns])
{
  for (int i = 0; i &lt; rows; i = i + 1)
    for (int j = 0; j &lt; columns; j = j + 1)
    {
      array[i][j].variable_1 = 0;
      array[i][j].variable_2 = 0;
      array[i][j].variable_3 = 0;
    }
}

int main()
{
  unsigned long rows = 200;
  unsigned long columns = 250;
  cell* array[rows];
  for (unsigned long i = 0; i &lt; rows; i = i + 1)
    array[i] = malloc(columns * sizeof(cell));


  if (array == NULL)
  {
    printf(&quot;Error in &quot;&quot;main&quot;&quot;: Memory could not be allocated.\n&quot;);
    return 3;
  }

  initialiseArray(rows, columns, array);

  return 0;
}

答案1

得分: 6

cell* array[rows]; 是一个在栈上分配的可变长度数组(VLA);每一行都通过 array[i] = malloc(columns * sizeof(cell)); 在堆上分配。

我建议你要么在栈上,要么在堆上分配 array

  1. 栈:
	cell array[rows][columns];
	初始化数组(rows, columns, array);

值得一提的是,你不能初始化 VLAs,所以你仍然需要 初始化数组()(或使用 memset())。在Linux上,默认的堆栈大小为8 MB,如果尝试使用超过这个大小,你的程序可能会导致段错误。

  1. 堆:
	cell (*array)[rows][columns] = malloc(sizeof *array);
	初始化数组(rows, columns, *array);

正如 @yano 提到的,你可以使用 calloc() 来对内存进行零初始化,因此不一定需要调用 初始化数组()。在Linux上,限制取决于可用的物理内存加上交换空间(例如,16 GB),如果尝试使用超过可用内存,malloc() / calloc() 将返回NULL,你可以轻松处理。

在这种情况下,两种方式都可以。如果 rowscolumns 只在运行时知道,建议使用堆分配。

建议传递变量而不是 sizeof 的类型。

虽然 ij 是完全有效的循环变量,但在这种情况下,考虑使用 r / rowc / col / column 更为合适。

英文:

cell* array[rows]; is a variable length array (VLA) that is allocated on the stack; each row is allocated on the heap with array[i] = malloc(columns * sizeof(cell));.

I suggest you either allocate the array on the stack or heap:

  1. Stack:
	cell array[rows][columns];
	initialiseArray(rows, columns, array);

You cannot initilaize VLAs, btw, so you still need initialiseArray() (or use memset()). On Linux the default stack size is 8 MB, and if you try to use more than that your program will probably segfault.

  1. Heap:
	cell (*array)[rows][columns] = malloc(sizeof *array);
	initialiseArray(rows, columns, *array);

As @yano mentioned you can use calloc() to zero initialize your memory so you don't necessarily need to call initialiseArray(). On Linux the limit is whatever amount of free physical memory + swap (say, 16 GB), and if you try to use more than available malloc() / calloc() will return NULL which you can easily handle.

Either is in fine in this case. If rows and columns are only known at run-time prefer heap allocation.

Prefer passing variable instead of a type of sizeof.

While i and j are perfectly valid loop variables consider using r / row or c / col / column in this case.

答案2

得分: 1

请看一下警告信息,您有许多问题,其中一些更为严重。最严重的问题是initialiseArray函数的array参数。当您将数组作为参数传递给函数时,它会“衰减”为指向第一个元素的指针。您有一个cell指针类型的数组,或者说cell*类型的数组。因此,这种类型的指针是cell**类型,所以您应该将参数更改为:

void initialiseArray(unsigned long rows, unsigned long columns, cell** array)

您应该修复的其他警告包括:

  1. initialiseArray中将intunsigned long进行比较。
  2. 检查if (array == NULL)是没有意义的,因为它是自动存储中的数组,永远不会为NULL。相反,您应该检查if (array[i] == NULL),所以将该检查移到执行malloc的循环中。
void initialiseArray(unsigned long rows, unsigned long columns, cell** array)
{
  for (unsigned long i = 0; i < rows; i = i + 1)
    for (unsigned long j = 0; j < columns; j = j + 1)
    {
      array[i][j].variable_1 = 0;
      array[i][j].variable_2 = 0;
      array[i][j].variable_3 = 0;
    }
}

int main(void)
{
  unsigned long rows = 200;
  unsigned long columns = 250;
  cell* array[rows];
  for (unsigned long i = 0; i < rows; i = i + 1)
  {
    array[i] = calloc(sizeof(cell), columns);
    if (array[i] == NULL)
    {
        printf("Error in \"main\": Memory could not be allocated.\n");
        return 3;
    }
  }

  initialiseArray(rows, columns, array);

  return 0;
}

但由于您将内存初始化为0,实际上根本不需要initialiseArray函数,只需使用calloc分配内存即可:

for (unsigned long i = 0; i < rows; i = i + 1)
{
  array[i] = calloc(sizeof(cell), columns);
  if (array[i] == NULL)
  {
    printf("Error in \"main\": Memory could not be allocated.\n");
    return 3;
  }
}

现在您的内存已被清零,无需自己编写函数。

最后,请不要忘记在程序结束时清理分配的内存,如果您选择这样做

英文:

Take a look at the warnings, you have a number of issues, some more serious that others. The most egregious violation is the array argument of initialiseArray. When you pass an array to a function as an argument, it decays to a pointer to the first element. You have an array of cell pointer types, or cell* types. So a pointer to this type is a cell** type, so that's what you should change the argument to:

void initialiseArray(unsigned long rows, unsigned long columns, cell** array)

Additional warnings that you should fix:

  1. Comparing int to unsigned long in initialiseArray
  2. Checking if (array == NULL) makes no sense, it's an array in automatic storage, it will never be NULL. Instead, you mean to check if (array[i] == NULL), so move that check into the loop that's doing the mallocing.
void initialiseArray(unsigned long rows, unsigned long columns, cell** array)
{
  for (unsigned long i = 0; i &lt; rows; i = i + 1)
    for (unsigned long j = 0; j &lt; columns; j = j + 1)
    {
      array[i][j].variable_1 = 0;
      array[i][j].variable_2 = 0;
      array[i][j].variable_3 = 0;
    }
}

int main(void)
{
  unsigned long rows = 200;
  unsigned long columns = 250;
  cell* array[rows];
  for (unsigned long i = 0; i &lt; rows; i = i + 1)
  {
    array[i] = calloc(sizeof(cell), columns);
    if (array[i] == NULL)
    {
        printf(&quot;Error in &quot;&quot;main&quot;&quot;: Memory could not be allocated.\n&quot;);
        return 3;
    }
  }

  initialiseArray(rows, columns, array);

  return 0;
}

But since you're initializing your memory to 0, there's really no need for the initialiseArray function at all, simply allocate with calloc:

for (unsigned long i = 0; i &lt; rows; i = i + 1)
{
  array[i] = calloc(sizeof(cell), columns);
  if (array[i] == NULL)
  {
    printf(&quot;Error in &quot;&quot;main&quot;&quot;: Memory could not be allocated.\n&quot;);
    return 3;
  }
}

Now your memory is zeroized, no need to roll your own function.

Finally, don't forget to clean up your allocated memory if you so choose

huangapple
  • 本文由 发表于 2023年5月21日 09:08:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/76297907.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定