我很难完全理解发生了什么。
这就是我在底部阅读代码的方式。
将A定义为指向指向指针的地址的指针 双人的地址。
在堆上分配4个内存块,每个内存块可以容纳一个内存块 地址为双。返回分配的第一个块的地址 到A.
在堆上分配6个内存块,每个内存块可以容纳一个双倍内存 数据类型并返回每个4的第一个块的地址 早先分配的块。
变量A仍然包含四个中第一个块的地址 假设A [0]改变了指向地址的值 由A而不是A本身。
现在这是图表的底部链接的地方。让我们说我想访问存储在红色块中的数据。我该怎么做?
以下代码是否有效?
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));
}
图:
旁注: 我是电气工程专业的学生,在某种程度上不熟悉C和正式的编程实践。我知道我对这么简单的代码行很迂腐,但我想确保我正确理解指针和内存分配。乍一看他们很难理解。这是我教授给我的矩阵乘法代码的一部分,我希望将指针传递给函数并让它访问并修改内存中的正确值。个人希望看到这个代码的二维数组,但我假设有一个很好的理由。
答案 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
使用了您尚未获得写入权限的空间。