[英]allocate memory for 2d array c
我阅读了很多有关分配内存的文章,并且我认为我理解了这个概念,但是有人告诉我,我必须使用一种类似于以下内容的方法:
double ** malloc_array2d(size_t m, size_t n)
{
double **A;
size_t i;
A = malloc(m * sizeof(double *));
if (A == NULL)
return NULL;
A[0] = (double *) malloc(m * n * sizeof(double));
if (A[0] == NULL)
{
free(A);
return NULL;
}
for (i = 1 ; i < m ; i++)
A[i] = A[0] + i *n;
return A;
}
然后当然,我以后必须释放内存-但我只是不太了解这种方法,更具体地说,我无法真正看到最后一行中剩余的指针设置到块中的情况。内存(有人告诉我。我不确定分配完成后如何在矩阵/数组中插入元素。
使用这种分配形式,您首先需要将一个指针数组分配给其他数组,如下所示:
T **a = malloc( sizeof *a * N ); // N is the number of rows
sizeof *a
等于sizeof (T *)
; 数组的每个元素都将是T
的指针。 完成后,内存中将包含以下内容:
+---+
a: | | a[0]
+---+
| | a[1]
+---+
| | a[2]
+---+
...
+---+
| | a[N-1]
+---+
现在,对于每个这些元素,我们分配另一个内存块来保存T
类型的每个元素:
a[i] = malloc( sizeof *a[i] * M ); // M is the number of columns
每个a[i]
类型均为T *
,因此sizeof *a[i]
等效于sizeof (T)
。
完成之后,我们在内存中看起来像这样:
+---+ +---------+---------+ +-----------+
a: | | a[0] ---> | a[0][0] | a[0][1] |...| a[0][M-1] |
+---+ +---------+---------+ +-----------+
| | a[1] ---> | a[1][0] | a[1][1] |...| a[1][M-1] |
+---+ +---------+---------+ +-----------+
| | a[2] ---> | a[2][0] | a[2][1] |...| a[2][M-1] |
+---+ +---------+---------+ +-----------+
...
+---+ +-----------+-----------+ +-------------+
| | a[N-1]--> | a[N-1][0] | a[N-1][1] |...| a[N-1][M-1] |
+---+ +-----------+-----------+ +-------------+
因此,基本上您在这里所做的就是分配N
单独的T
M
元素数组,然后在T *
个N
元素数组中收集指向这些数组的指针。
您可以像对待任何普通2D数组一样,以a[i][j]
访问每个元素。 请记住,表达式a[i]
定义为*(a + i)
; 我们抵消i
从地址元素( 而不是字节!)的a
,然后解引用的结果。 因此a[i][j]
的值为*(*(a + i) + j )
。
因此,使用这种分配方式要记住几件事:
数组的“行”在内存中不会是连续的。 a[i][M-1]
之后a[i][M-1]
内存中的对象(很可能)不会是a[i+1][0]
。
由于每个“行” a[i]
与一个呼叫分配malloc
,它也必须明确将其相应的呼叫释放,以free
取消分配之前 a
(总是free
相反的顺序,你malloc
)。
即使我们可以将a
视为2D数组,它也没有数组类型,因此您无法使用sizeof a
技巧来确定数组的sizeof a
; 您只会得到指针类型的大小,而不是数组的总大小。 因此,您需要自己跟踪数组大小。
double ** malloc_array2d(size_t m, size_t n){
double **A;
size_t i;
A = malloc(m*sizeof(double *));
if (A == NULL) return NULL;
A[0]=(double *)malloc(m*n*sizeof(double));
if ( A[0] == NULL) {free(A); return NULL;}
for(i=1; i<m; i++) A[i]=A[0]+i*n;
return A;
}
让我们一行一行地去:
A = malloc(m*sizeof(double *));
该行为m个双指针分配空间。
A[0] = (double *) malloc(m*n*sizeof(double));
A [0]现在是一个内存块,用于m * n个double,这是我们2d数组所需的所有double。
for (int i = 1; i < m; i++) {A[i] = A[0] + i * n;}
因为每个A [i]都是n个double的块,所以我们希望A [i]从a [0]开始i * n个double。
因为所有这些都存储在坚固的内存块中,所以我们可以做一些有趣的事情。 例如,A [0] [n]与A [1] [0]完全相同。
此外,由于所有内容都在一个大的内存块中,因此要访问A [i] [j]的任何i <m,j <n,我们只需要访问A[0] + i*j + j
的双A[0] + i*j + j
。 这比转到指向双* B并找到B [j]的A [i]快得多。
内存管理是一个很难理解的主题,需要花费一些时间。 希望这更有意义,我希望我不要再让您感到困惑了:)
您必须使Poitners指针的每个指针指向有效的malloc()
ed数据。
for (int i = 0 ; i < n ; ++i)
A[i] = (double *) malloc(m * sizeof(double));
您也可以一次分配全部,但是符号A[i][j]
将不起作用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.