简体   繁体   English

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

[英]Confused about Pointers to Pointers and Dynamic Memory Allocation

I am having a difficult time fully understanding what is going on. 我很难完全理解正在发生的事情。

This is how I am reading the code at the bottom. 这就是我在底部阅读代码的方式。

  1. Define A as a pointer to an address of a pointer that points to address of a double. 将A定义为指向指向double地址的指针地址的指针。

  2. Allocate 4 blocks of memory on the heap that can each hold an address to a double. 在堆上分配4个内存块,每个内存块可以将地址保存为double。 Return the address of the first block allocated to A. 返回分配给A的第一个块的地址。

  3. Allocate 6 blocks of memory on the heap that can each hold a double data type and return the first block's address for each of the 4 blocks allocated earlier. 在堆上分配6个内存块,每个内存块可以保存双数据类型,并为之前分配的4个块中的每个块返回第一个块的地址。

  4. Variable A still contains the address of the first block of the four pointers assuming that A[0] changed the value at the address pointed by A rather than A itself. 变量A仍然包含四个指针的第一个块的地址,假设A [0]改变了A指向的地址而不是A本身的值。

Now this is where the diagram comes in that is linked at the bottom. 现在这是图表的底部链接的地方。 Lets say that I wanted to access the data stored in the red block. 让我们说我想访问存储在红色块中的数据。 How would I do so? 我该怎么办?

Would the following code work? 以下代码是否有效?

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

My logic is that A is a pointer and incrementing by 3 should increase the address by the number of bytes that is of the size (double *). 我的逻辑是A是一个指针,递增3应该增加地址的大小(double *)的字节数。 Dereferencing the address (A + 3), I would obtain the address of first block (assuming it was not re-assigned). 取消引用地址(A + 3),我将获得第一个块的地址(假设它没有被重新分配)。 By increasing the resulting address by 2 and dereferencing that address, I should obtain the value at the red block. 通过将结果地址增加2并取消引用该地址,我应该获得红色块的值。

So if I understand correctly, 1 + M pointers are being stored in memory. 因此,如果我理解正确,1 + M指针存储在内存中。 Why? 为什么? If the goal is to store MxN data, why would I need 1 + M pointers to do so? 如果目标是存储MxN数据,为什么我需要1 + M指针才能这样做? The extra pointers seem like they would be helpful if I wanted to define rows of different sizes but the objective is to define a rectangular array of data. 如果我想定义不同大小的行但是目标是定义矩形数据数组,额外的指针似乎会有用。

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));
}

Diagram: 图:

在此输入图像描述

Side Note: I am Electrical Engineering student that is unfamiliar with C to some degree and formal programming practices. 旁注:我是电气工程专业的学生,​​在某种程度上不熟悉C和正式的编程实践。 I know that I'm being pedantic about the such a simple line of code, but I want to be sure that I understand pointers and memory allocation correctly. 我知道我对这么简单的代码行很迂腐,但我想确保我正确理解指针和内存分配。 They are pretty hard to comprehend at first glance. 乍一看他们很难理解。 This is part of a matrix multiplication code given to me by my professor and I want to pass the pointer to a function and have it access and modify the correct values in memory. 这是我教授给我的矩阵乘法代码的一部分,我希望将指针传递给函数并让它访问并修改内存中的正确值。 Personally would of liked to see two-dimensional arrays for this code, but I am assuming that there is a good reason. 个人希望看到这个代码的二维数组,但我假设有一个很好的理由。

You can also store this contiguously and just do the math instead of letting the compiler do it for you 你也可以连续存储它,只是做数学而不是让编译器为你做

So: 所以:

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);
}

this will save all the indirection since you know the size 这将保存所有间接,因为你知道大小

If you don't need to allocate sizes dynamically this is what 如果您不需要动态分配大小,那就是这样

double A[17][14] will do for you on the stack double A[17][14]将在堆栈中为你做

Yes, double data = *(*(A + 3) + 2); 是的, double data = *(*(A + 3) + 2); would work, and access the "red" double. 会工作,并访问“红色”双。

I guess your professor will tell you soon that A[3][2] works as well, is much easier to read, and preferable to *(*(A + 3) + 2); 我想你的教授很快就会告诉你A[3][2]也可以,更容易阅读,并且优于*(*(A + 3) + 2);

Lesson learned (not yet, but what your professor is trying to teach to you): in C, multidimensional arrays are not something like 'a table with N columns and M rows', in C, all arrays are really pointers, and multidimensional arrays are implemented as pointers to pointers. 教训(目前还没有,但你的教授正试图教给你):在C,多维数组不是像“与N列和M行的表”,在C,所有的数组是真正指针和多维数组被实现为指针的指针。 Whenever your write A[3][2] , *(*(A + 3) + 2) is what really happens internally. 每当你写A[3][2]*(*(A + 3) + 2)是内部真正发生的事情。 This, in turn, explains why you can't allocate a N*M matrix in one statement; 这反过来解释了为什么你不能在一个陈述中分配N * M矩阵; you have to allocate the "row pointers" first, then allocate the "columns" for each of the row pointer. 你必须首先分配“行指针”,然后为每个行指针分配“列”。

malloc(M*sizeof(double *)) says: "Give me a pointer to M double pointers." malloc(M*sizeof(double *))说:“给我一个指向M双指针的指针。” malloc(N*sizeof(double)) says: "Give me a pointer to N doubles." malloc(N*sizeof(double))说:“给我一个指向N双打的指针。” Now notice the bug: 现在注意错误:

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

A points to an array of M double pointers, but you are writing N entries into it (where each entry is a pointer to N doubles). A点至M双指针数组,但你正在写N个条目进去(其中每个条目是一个指针到N加倍)。 If M > N you waste space, and if M < N you use space that you haven't asked permission to write to. 如果M > N浪费空间,如果M < N ,则使用未经许可写入的空间。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM