对指针指针和动态内存分配感到困惑

时间:2013-12-08 21:09:33

标签: c pointers memory memory-management

我很难完全理解发生了什么。

这就是我在底部阅读代码的方式。

  1. 将A定义为指向指向指针的地址的指针 双人的地址。

  2. 在堆上分配4个内存块,每个内存块可以容纳一个内存块 地址为双。返回分配的第一个块的地址 到A.

  3. 在堆上分配6个内存块,每个内存块可以容纳一个双倍内存 数据类型并返回每个4的第一个块的地址 早先分配的块。

  4. 变量A仍然包含四个中第一个块的地址 假设A [0]改变了指向地址的值 由A而不是A本身。

  5. 现在这是图表的底部链接的地方。让我们说我想访问存储在红色块中的数据。我该怎么做?

    以下代码是否有效?

    double data = *(*(A + 3) + 2);
    

    我的逻辑是A是一个指针,递增3应该增加地址的大小(double *)的字节数。取消引用地址(A + 3),我将获得第一个块的地址(假设它没有被重新分配)。通过将结果地址增加2并取消引用该地址,我应该获得红色块的值。

    因此,如果我理解正确,1 + M指针存储在内存中。为什么?如果目标是存储MxN数据,为什么我需要1 + M指针才能这样做?如果我想定义不同大小的行,但是目标是定义一个矩形的数据数组,那么额外的指针似乎会有所帮助。

    const int M = 4;
    const int N = 6;
    double **A;
    
    A = malloc(M*sizeof(double *));
    
    for (i = 0; i < N; i++) {
        A[i]= malloc(N*sizeof(double));
    }
    

    图:

    enter image description here

    旁注: 我是电气工程专业的学生,​​在某种程度上不熟悉C和正式的编程实践。我知道我对这么简单的代码行很迂腐,但我想确保我正确理解指针和内存分配。乍一看他们很难理解。这是我教授给我的矩阵乘法代码的一部分,我希望将指针传递给函数并让它访问并修改内存中的正确值。个人希望看到这个代码的二维数组,但我假设有一个很好的理由。

3 个答案:

答案 0 :(得分:3)

你也可以连续存储它,只是做数学而不是让编译器为你做这个

所以:

double * A = malloc (M * N * sizeof(double));

double get(double * what, cur_x, cur_y, max_x, max_y)
{
    return *(what+cur_x*max_y+cur_y);
}

这将保存所有间接,因为你知道大小

如果您不需要动态分配大小,那么

double A[17][14]将在堆栈中为您完成

答案 1 :(得分:2)

是的,double data = *(*(A + 3) + 2);可以使用,并访问“红色”双倍。

我猜你的教授很快会告诉你,A[3][2]也有效,更容易阅读,更适合*(*(A + 3) + 2);

经验教训(还没有,但是你的教授试图教给你的):在C中,多维数组类似'带有N列和M行的表',在C中,所有数组都是指针,多维数组实现为指针指针。每当你写A[3][2]*(*(A + 3) + 2)时,内部真正发生了什么。这反过来解释了为什么你不能在一个陈述中分配N * M矩阵;你必须先分配“行指针”,然后为每个行指针分配“列”。

答案 2 :(得分:2)

malloc(M*sizeof(double *))说:&#34;给我一个指向 M 双指针的指针。&#34; malloc(N*sizeof(double))说:&#34;给我一个指向 N 双打的指针。&#34; 现在请注意错误:

for (i = 0; i < N; i++) {
    A[i]= ...;
}

A指向 M 双指针数组,但您正在将 N 条目写入其中(其中每个条目都是指向的指针) N 加倍)。如果M > N您浪费了空间,并且M < N使用了您尚未获得写入权限的空间。