作为一名初学C / C ++程序员,我不得不花费几个小时,试图破译下面的代码:有人可以一行一步地跟我走(请通过以下代码进行动态内存分配)。
char **alloc_2d_char(const int rows, const int cols)
{
char *data = (char *)malloc(rows*cols*sizeof(char));
char **array= (char **)malloc(rows*sizeof(char*));
for (int i=0; i<rows; i++)
array[i] = &(data[cols*i]);
return array;
}
Pointers指针的解释与Pointers to Arrays不同。我已经能够从各种来源获得部分信息,但没有一个能够内聚地缝合线条。
答案 0 :(得分:5)
代码使用单个连续的内存块来容纳二维数组。
char *data = (char *)malloc(rows*cols*sizeof(char));
好的 - 这条线为整个二维阵列分配空间。 2-D数组是rows
列cols
列。所以元素的总数是rows * cols
。然后你必须乘以每个元素占用的空间量,即sizeof(char)
,因为这是char
的二维数组。因此,要分配的内存总量为rows * cols * sizeof(char)
,这确实是malloc
的参数。
malloc
调用返回指向已分配内存的指针。由于此内存将用于保存char
,因此您将返回值转换为char *
。
char **array= (char **)malloc(rows*sizeof(char*));
array
被声明为类型“指向char的指针”,因为这就是它要做的事情。它将指向将保存指向char的指针的内存。它将是每行的一个指针。所以你必须分配rows * sizeof(char *)
内存:指针的数量乘以正确类型的指针的大小。由于这是分配给指向char的指针,我们将返回值转换为char **
。
for (int i=0; i<rows; i++)
array[i] = &(data[cols*i]);
这是神奇的:)。这会将array
中的每个指针设置为指向在之前分配的实际数据块中。考虑一个具体的例子,rows
为2,cols
为3.然后你在内存中有6个字符的块:
[0][1][2][3][4][5]
data[n]
(n
从0
到5
)是第n个元素,&data[n]
是* 地址第n个元素的em>。
那么在这种情况下循环的作用是:
array[0] = &data[0];
array[1] = &data[3];
因此array[0]
指向从[0]
开始的子块,array[1]
指向从[3]
开始的子块。然后,当您添加第二个下标时,您将从该指针的开头编制索引。因此array[0][2]
表示“将指针存储在array[0]
中。找到它指向的内容,然后从那里向前移动2个元素。:
array[0]
指向[0][1][2]
(实际上,指向[0]
)。然后你向前移动两个元素并获得[2]
。
如果您从array[1][1]
开始,array[1]
指向[3][4][5]
(实际指向[3]
。请提前移动一个元素并获取[4]
。< / p>
答案 1 :(得分:1)
第一个malloc正在获取2D字符数组的内存。第二个malloc为行索引获取内存。
for循环将指针设置为每一行。
最后返回行索引。
答案 2 :(得分:1)
您可以将其创建的二维数组视为一维数组的数组。每个行条目都指向一个char数组,表示该行的列数据。
以下是原始代码,添加了注释以尝试描述每个步骤:
char **alloc_2d_char(const int rows, const int cols)
{
// This allocates the chunk of memory that stores that actual data.
// It is a one single-dimensional array that has rows*cols characters.
char *data = (char *)malloc(rows*cols*sizeof(char));
// This allocates an array of pointers that will then be assigned to the
// individual rows (carved out of the previous allocation).
char **array= (char **)malloc(rows*sizeof(char*));
// This assigns each row to the appropriate position in the data array.
// The &(data[cols*i]) bit of it is the address of a portion in the
// memory pointed to by data. The cols*i is the offset to the portion that
// represents row i.
for (int i=0; i<rows; i++)
array[i] = &(data[cols*i]);
// After doing this, then you can assign a value such as:
// array[r][c] = 'x';
// That statement would store 'x' into data[r*c + c]
return array;
}
答案 3 :(得分:1)
难以破译......
char *data = (char *)malloc(rows*cols*sizeof(char));
简单的内存分配
char **array= (char **)malloc(rows*sizeof(char*));
#row char指针的内存分配
array[i] = &(data[cols*i]);
每个数组[i]都是一个指针,一个指向数据[cols * i]
的指针答案 4 :(得分:1)
声明中的每个*
都指向一个指针间接层。所以int **
表示指向int的指针。所以你的功能:
char **alloc_2d_char(const int rows, const int cols)
{
返回指向char的指针。
char *data = (char *)malloc(rows*cols*sizeof(char));
这声明了一个指向char
的指针。指针名为data
。初始化调用malloc
,它分配一些等于参数值的字节。这意味着有rows*cols*sizeof(char)
个字节,它们将等于rows*cols
,因为char
是1个字节。 malloc
函数返回指向新内存的指针,这意味着data
现在指向一块rows*cols
大的内存。调用(char *)
之前的malloc
只是将新内存转换为与指针data
相同的类型。
char **array= (char **)malloc(rows*sizeof(char*));
array
是指向char
指针的指针。它也是使用malloc
分配的。此次分配的内存量为rows*sizeof(char)
,等于rows
。这意味着array
是指向一大块内存的指针,该内存大到足以容纳1行。
for (int i=0; i<rows; i++)
array[i] = &(data[cols*i]);
其余代码初始化array
的每个元素以保存大块内存的相应行的地址。你的data
指针将指向一块如下所示的内存:
col: 0 1 2 3 ... cols-1
row: 0 *
1 *
2 *
3 *
.
.
.
rows-1 *
你的array
指针将指向一块带有指针列表的内存块,每个指针指向上面内存块中的一个星号。
return array;
}
这只会返回指向指针的array
指针,该指针与alloc_2d_char
函数的返回类型匹配:char **
。这意味着函数的调用者将基本上获得一个指针数组,并且这些指针中的每一个都指向2D数组的一行。