int **a = malloc2d(M, N) // dynamically allocates a 2D array
Run Code Online (Sandbox Code Playgroud)
int int a an int int*a 的目的是什么?我知道动态分配需要指针,但为什么有一个指针指针?
对于三维数组,它将是:
int ***a
Run Code Online (Sandbox Code Playgroud)
?
出于几个原因,您需要指向指针的指针.
在您给出的示例中,双指针用于存储2D数组.
C中的2D数组被视为一维数组,其元素是一维数组(行).
例如,Tx的4x3数组(其中"T"是某种数据类型)可以通过以下方式声明:"T mat [4] [3]",并通过以下方案描述:
+-----+-----+-----+
mat == mat[0] ---> | a00 | a01 | a02 |
+-----+-----+-----+
+-----+-----+-----+
mat[1] ---> | a10 | a11 | a12 |
+-----+-----+-----+
+-----+-----+-----+
mat[2] ---> | a20 | a21 | a22 |
+-----+-----+-----+
+-----+-----+-----+
mat[3] ---> | a30 | a31 | a32 |
+-----+-----+-----+
Run Code Online (Sandbox Code Playgroud)
另一种情况是,当你传递一个指向函数的指针时,你希望该函数分配该指针.为此,您必须指向变量的地址,因此指向指针
void make_foofoo(int** change) {
*change = malloc(4);
}
Run Code Online (Sandbox Code Playgroud)
在C中,指向类型的指针指向存储T某些类型数据的位置T.为了保持具体,我将在T = int下面讨论.
指针最简单的用法可能是指向一个值:
int a = 42;
int *pa = &a;
Run Code Online (Sandbox Code Playgroud)
现在,*pa和a都是相同的,等于42.此外,*pa和pa[0]都是相同的:因此,举例来说,你可以这样做:
*pa += 1; /* a is 43 */
pa[0] += 1; /* a is 44 */
a += 1; /* a is 45 */
Run Code Online (Sandbox Code Playgroud)
实际上,C编译器pa[0]会*(pa+0)自动转换为.
指针可以指向数据序列内的位置:
int arr[] = { 1, 2, 3 }; /* 3 ints */
int *parr = arr; /* points to 1 */
Run Code Online (Sandbox Code Playgroud)
现在,我们的记忆如下:
+---+---+---+
arr: | 1 | 2 | 3 |
+---+---+---+
+------+ |
| parr | ----+
+------+
Run Code Online (Sandbox Code Playgroud)
parr是指向arr上图中第一个元素的指针.顺便说一下,parr它周围也有一个框,因为我们需要将对象存储parr在内存中的某个位置.值parr是第一个元素的地址arr.
现在,我们可以parr用来访问以下元素arr:
arr[0] == parr[0]; /* true */
parr[1]++; /* make arr[1] equal to 3 */
Run Code Online (Sandbox Code Playgroud)
因此,指针可用于表示"我指向某些对象的连续存储中的n个元素中的第一个".当然,人们必须知道这个方案有多少对象可以工作:但是一旦我们记得这样做,这是一种非常方便的方式来访问C中的内存.
指针也可以指向动态分配的内存:
#include <stdlib.h>
size_t n;
/* now, obtain a value in n at runtime */
int *p = malloc(n * sizeof *p);
Run Code Online (Sandbox Code Playgroud)
如果malloc()呼叫成功,则p现在指向分配10 int秒的连续区域中的第一个.我们可以使用p[0]通过p[n-1]现在在我们的节目.
你可能知道上面的大部分或全部:-),但是,上面的内容有助于理解我接下来会说些什么.
还记得我们说指针可以指向相同类型的连续对象序列吗?"相同类型"也可以是另一种指针类型.
#include <stdlib.h>
int **pp;
pp = malloc(3 * sizeof *pp);
Run Code Online (Sandbox Code Playgroud)
现在,pp指向一个int *.回到我们之前的图片:
+------+------+------+
| | | |
+------+------+------+
+------+ |
| pp | ----+
+------+
Run Code Online (Sandbox Code Playgroud)
并且3个框中的每一个都是一个int *,它可以指向ints 的连续序列的第一个元素:
for (i=0; i < 3; ++i)
pp[i] = malloc((i + 1) * sizeof *ppi[i]);
Run Code Online (Sandbox Code Playgroud)
在这里,我们为一个int in pp[0],in 2 pp[1]和3 分配了空间pp[3]:
+------+ +---+
pp -------->| |-------->| |
+------+ +---+---+
| |-------->| | |
+------+ +---+---+---+
| |-------->| | | |
+------+ +---+---+---+
Run Code Online (Sandbox Code Playgroud)
所以,pp[0]是指向一个的指针int,这int是int动态分配的ints 块中的唯一指针.换句话说,pp[0][0]是一个int,并指向上面最顶部的"宽度-3"框.同样,pp[1][0]并且pp[1][1]都是有效的,并且是方框下方的两个方框pp[0][0].
指向指针的最常见用法是在运行时创建一个二维"数组":
int **data;
size_t i;
data = malloc(n * sizeof *data);
for (i=0; i < n; ++i)
data[i] = malloc(m * sizeof *data[i]);
Run Code Online (Sandbox Code Playgroud)
现在,假设所有malloc()s成功,data[0]... data[n-1]是有效值int *,每个值指向一个单独的长度m连续int对象.
但是,正如我在上面所示,指向指针的指针不需要在每个"行"中具有相同的"元素数量".最明显的例子是argv在main().
到目前为止,你可以猜到,一个"3级深度"指针,如int ***p;可以,可以在C中使用.