为二维数组 c 分配内存
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;
}
然后当然我以后必须释放内存 - 但我只是不太理解这种方法,更具体地说,我真的看不到最后一行剩下的指针是什么设置到内存块中(有人告诉过我吗?我不确定完成分配后如何在 matrix/array 中插入元素。
你必须让指针指针的每个指针都指向有效的malloc()
ed数据。
for (int i = 0 ; i < n ; ++i)
A[i] = (double *) malloc(m * sizeof(double));
你也可以一次性全部分配,但那样的话 A[i][j]
就不行了。
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个双指针分配space。
A[0] = (double *) malloc(m*n*sizeof(double));
A[0]现在是m*n个double的内存块,也就是我们需要的二维数组的所有double。
for (int i = 1; i < m; i++) {A[i] = A[0] + i * n;}
因为每个 A[i] 都是 n 个双打的块,我们希望 A[i] 从 A[0] 开始 i*n 个双打。
因为所有这些都在一个固定的内存块中,所以我们可以做一些有趣的事情。例如,A[0][n] 与 A[1][0].
完全相同
此外,因为所有内容都在一个大内存块中,要访问任何 i < m、j < n 的 A[i][j],我们只需访问 A[0] + i*j + j
处的双精度数。这比转到指向 double* B 的 A[i] 并找到 B[j] 快得多。
内存管理是一个很难理解的话题,需要一些时间。希望这更有意义,我希望我没有让你更加困惑 :)
使用这种分配形式,您首先要分配一个指向其他数组的指针数组,如下所示:
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
单独的 M
元素数组 T
,然后你在 [=22] 中收集指向这些数组的指针=]-T *
的元素数组。
您可以像 a[i][j]
一样访问每个元素,就像任何普通的二维数组一样;请记住表达式 a[i]
被定义为 *(a + i)
;我们从 a
中的地址偏移 i
个元素( 不是字节!),然后取消引用结果。所以 a[i][j]
被评估为 *(*(a + i) + j )
.
因此,使用这种分配形式要记住几件事:
数组的"rows"在内存中不会连续; a[i][M-1]
之后内存中的对象(很可能)不会是 a[i+1][0]
。
由于每个 "row" a[i]
都是通过调用 malloc
分配的,因此还必须通过相应的调用 free
显式释放它在 之前,您释放 a
(总是 free
的顺序与您 malloc
的顺序相反)。
尽管我们可以将 a
视为二维数组,但它没有数组类型,因此您无法使用 [=43 确定数组的大小=] 把戏;你只会得到指针类型的大小,而不是数组的总大小。所以你会想要自己跟踪数组大小。
我已经阅读了很多关于分配内存的帖子,我认为我理解了这个概念,但是我被告知我必须使用如下所示的方法:
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;
}
然后当然我以后必须释放内存 - 但我只是不太理解这种方法,更具体地说,我真的看不到最后一行剩下的指针是什么设置到内存块中(有人告诉过我吗?我不确定完成分配后如何在 matrix/array 中插入元素。
你必须让指针指针的每个指针都指向有效的malloc()
ed数据。
for (int i = 0 ; i < n ; ++i)
A[i] = (double *) malloc(m * sizeof(double));
你也可以一次性全部分配,但那样的话 A[i][j]
就不行了。
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个双指针分配space。
A[0] = (double *) malloc(m*n*sizeof(double));
A[0]现在是m*n个double的内存块,也就是我们需要的二维数组的所有double。
for (int i = 1; i < m; i++) {A[i] = A[0] + i * n;}
因为每个 A[i] 都是 n 个双打的块,我们希望 A[i] 从 A[0] 开始 i*n 个双打。
因为所有这些都在一个固定的内存块中,所以我们可以做一些有趣的事情。例如,A[0][n] 与 A[1][0].
完全相同此外,因为所有内容都在一个大内存块中,要访问任何 i < m、j < n 的 A[i][j],我们只需访问 A[0] + i*j + j
处的双精度数。这比转到指向 double* B 的 A[i] 并找到 B[j] 快得多。
内存管理是一个很难理解的话题,需要一些时间。希望这更有意义,我希望我没有让你更加困惑 :)
使用这种分配形式,您首先要分配一个指向其他数组的指针数组,如下所示:
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
单独的 M
元素数组 T
,然后你在 [=22] 中收集指向这些数组的指针=]-T *
的元素数组。
您可以像 a[i][j]
一样访问每个元素,就像任何普通的二维数组一样;请记住表达式 a[i]
被定义为 *(a + i)
;我们从 a
中的地址偏移 i
个元素( 不是字节!),然后取消引用结果。所以 a[i][j]
被评估为 *(*(a + i) + j )
.
因此,使用这种分配形式要记住几件事:
数组的"rows"在内存中不会连续;
a[i][M-1]
之后内存中的对象(很可能)不会是a[i+1][0]
。由于每个 "row"
a[i]
都是通过调用malloc
分配的,因此还必须通过相应的调用free
显式释放它在 之前,您释放a
(总是free
的顺序与您malloc
的顺序相反)。尽管我们可以将
a
视为二维数组,但它没有数组类型,因此您无法使用 [=43 确定数组的大小=] 把戏;你只会得到指针类型的大小,而不是数组的总大小。所以你会想要自己跟踪数组大小。