英文:
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 <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;
}
答案1
得分: 6
cell* array[rows];
是一个在栈上分配的可变长度数组(VLA);每一行都通过 array[i] = malloc(columns * sizeof(cell));
在堆上分配。
我建议你要么在栈上,要么在堆上分配 array
:
- 栈:
cell array[rows][columns];
初始化数组(rows, columns, array);
值得一提的是,你不能初始化 VLAs,所以你仍然需要 初始化数组()
(或使用 memset()
)。在Linux上,默认的堆栈大小为8 MB,如果尝试使用超过这个大小,你的程序可能会导致段错误。
- 堆:
cell (*array)[rows][columns] = malloc(sizeof *array);
初始化数组(rows, columns, *array);
正如 @yano 提到的,你可以使用 calloc()
来对内存进行零初始化,因此不一定需要调用 初始化数组()
。在Linux上,限制取决于可用的物理内存加上交换空间(例如,16 GB),如果尝试使用超过可用内存,malloc()
/ calloc()
将返回NULL,你可以轻松处理。
在这种情况下,两种方式都可以。如果 rows
和 columns
只在运行时知道,建议使用堆分配。
建议传递变量而不是 sizeof
的类型。
虽然 i
和 j
是完全有效的循环变量,但在这种情况下,考虑使用 r
/ row
或 c
/ 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:
- 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.
- 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)
您应该修复的其他警告包括:
- 在
initialiseArray
中将int
与unsigned long
进行比较。 - 检查
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:
- Comparing
int
tounsigned long
ininitialiseArray
- Checking
if (array == NULL)
makes no sense, it's an array in automatic storage, it will never be NULL. Instead, you mean to checkif (array[i] == NULL)
, so move that check into the loop that's doing themalloc
ing.
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;
}
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 < 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;
}
}
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论