Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为2d数组c分配内存_C_Arrays_Malloc - Fatal编程技术网

为2d数组c分配内存

为2d数组c分配内存,c,arrays,malloc,C,Arrays,Malloc,我已经阅读了很多关于分配内存的帖子,我认为我理解这个概念,但是我被告知我必须使用一种类似这样的方法: 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 *

我已经阅读了很多关于分配内存的帖子,我认为我理解这个概念,但是我被告知我必须使用一种类似这样的方法:

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;
}
double**malloc\u array2d(大小为m,大小为n)
{
双**A;
尺寸i;
A=malloc(m*sizeof(double*);
如果(A==NULL)
返回NULL;
A[0]=(双*)malloc(m*n*sizeof(双));
如果(A[0]==NULL)
{
免费(A);
返回NULL;
}
对于(i=1;i

当然,稍后我将不得不释放内存-但我不太理解这种方法,更具体地说,我无法看到在最后一行剩余指针被设置到内存块中时发生了什么(有人告诉过我。我不确定分配完后如何在矩阵/数组中插入元素。

必须使poitners指针的每个指针指向有效的
malloc()
ed数据

for (int i = 0 ; i < n ; ++i)
    A[i] = (double *) malloc(m * sizeof(double)); 
for(int i=0;i
您也可以一次将其全部分配,但是表示法
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;
}
此行为m个双指针分配空间

A[0] = (double *) malloc(m*n*sizeof(double));
[0]现在是m*n倍的内存块,这是2d阵列所需的全部倍

for (int i = 1; i < m; i++) {A[i] = A[0] + i * n;}
(inti=1;i 因为每个A[i]是一个由n个双倍体组成的块,所以我们希望A[i]从A[0]开始i*n个双倍体

因为所有这些都在一个坚实的内存块中,所以我们可以做一些有趣的事情。例如,[0][n]与[1][0]完全相同

此外,因为所有东西都在一个大内存块中,要访问任何iA[0]+i*j+j。这比访问指向双*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]
   +---+
   +---+           +---------+---------+   +-----------+
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] |
   +---+           +-----------+-----------+   +-------------+
现在,对于这些元素中的每一个,我们分配另一块内存来保存
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[1]
   +---+
   |   | a[2]
   +---+
    ...
   +---+
   |   | a[N-1]
   +---+
   +---+           +---------+---------+   +-----------+
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][/code>被定义为
*(a+i)
;我们从
a
中的地址偏移
i
元素(不是字节!),然后取消对结果的引用。因此
a[i][j]
被计算为
*(*(a+i)+j)

因此,在这种分配形式中需要记住几点:

  • 数组的“行”在内存中不会是连续的;
    a[i][M-1]
    后面的内存对象(很可能)不会是
    a[i+1][0]

  • 由于每个“行”
    a[i]
    都分配了对
    malloc
    的调用,因此在解除分配
    a
    之前,还必须显式地解除分配给
    free
    (始终以与
    malloc
    相反的顺序解除分配
    free

  • 尽管我们可以将
    a
    视为2D数组,但它没有数组类型,因此您无法使用
    sizeof a
    技巧确定数组的大小;您只能获得指针类型的大小,而不是数组的总大小。因此,您需要自己跟踪数组大小


  • 你可以随时用谷歌搜索。你也可以保持一致,你第二次抛出
    malloc()
    时根本不要这样做,或者即使是丑陋的、不必要的,也要这样做,但要保持一致。对于
    ,循环非常小,试着取一些具体的小值(比如
    m=n=2
    )写下函数的作用,扩展循环迭代。为分配的块和指针绘制框和箭头…如果你仍然看不到发生了什么,请解释你理解的位。这不是一个2D数组,而是一个奇怪的数组模拟。这属于博物馆,现代C可以比C99做得更好。只需使用
    double(*arr)[m]=malloc(sizeof(double[n][m]));
    一次分配一个2D数组。你甚至不需要一个特殊的函数。问题中的代码确实有效。它一次分配所有数组,然后将指针放入分配的块中。是的,我想这是我在谷歌搜索时看到的最常见的方法——这在我的头脑中是有意义的——但我刚刚被告知这是最简单的方法“天真”的方法,一个更快的方法是分配一个大内存块m*n,然后设置指针到这个内存块中——我的书说这样做:)谢谢!这完全有道理:)