有人可以解释指向我的指针吗
Can someone explain pointers to pointers to me
我们最近在大学里谈到了指向指针的指针(例如:char **ppch
),根据我的理解,它们可以用作二维数组,因为 char *pch
,例如可以作为char
/string
.
的数组
是这样还是我漏掉了什么?我不确定我们如何在程序中使用 P2P,或者我的理解是否接近正确。
有人可以举个例子吗?我们是否需要为这些 P2P 中的每个元素分配 malloc()
的内存?
数组的固有特性属性是,它们的元素在内存中是连续的。例如
int foo[] = { 1, 2, 3, 4, 5, /* ... */ };
// ~> 1, 2, 3, 4, 5, ...
二维数组也不例外:
int bar[][3] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
// ~> 1, 2, 3, 4, 5, 6, 7, 8, 9
但是指向某种类型指针的指针
int **qux;
就是这样。指向一个指针(或多个指针)的指针。当你分配内存时
int **qux = malloc(N * sizeof(*qux));
你得到一个指向内存区域的指针,该内存区域的大小足以容纳 N
指向 int
的指针,后者又可以指向其他内存区域:
int **qux = malloc(N * sizeof(*qux));
int value = 0;
for (size_t i = 0; i < N; ++i) {
qux[i] = malloc(P * sizeof(**qux));
for (size_t k = 0; k < P; ++k)
qux[i][k] = ++value;
}
在记忆中看起来像
+----------+ +-----+
| qux[0] --|------------------------------|-> 1 |
| qux[1] --|-----------+ | 2 |
| qux[2] --|---+ | +-----+ | 3 |
| ... | | +-------|-> 4 | +-----+
+----------+ | | 5 |
| +-----+ | 6 |
+----|-> 7 | +-----+
| 8 |
| 9 |
+-----+
所以不,指向指针的指针不是二维数组。像这样的东西更像是 "jagged array".
至于你的字符串示例,没有区别:
char **qux; // a pointer to a (number of) pointers to char
qux = malloc(N * sizeof(*foo));
// just an array to fill the memory qux points to with:
char const *source[] = { "foo", "bar", "baz", "qux" /* I'm running out of names */ };
size_t index = 0;
for (size_t i = 0; i < N; ++i) {
qux[i] = malloc((strlen(source[index]) + 1) * sizeof(**qux));
strcpy(qux[i], source[index++]);
}
~>
+----------+ +--------+
| foo[0] --|------------------------------------------------------|-> 'f' |
| foo[1] --|-----------------------------------+ | 'o' |
| foo[2] --|----------------------+ | +--------+ | 'o' |
| foo[3] --|---+ | +----|-> 'b' | | '[=17=]' |
| ... | | | | 'a' | +--------+
+----------+ | +--------+ | +--------+ | 'r' |
+----|-> 'q' | +---|-> 'b' | | '[=17=]' |
| 'u' | | 'a' | +--------+
| 'x' | | 'z' |
| '[=17=]' | | '[=17=]' |
+--------+ +--------+
相比之下,char
s 的真实二维数组:
char foo[][4] = { "foo", "bar", "baz", "qux" /*, ... */ };
// ~> 'f', 'o', 'o', '[=18=]', 'b', 'a', 'r', '[=18=]', 'b', 'a', 'z', '[=18=]', 'q', 'u', 'x', '[=18=]', ...
我们最近在大学里谈到了指向指针的指针(例如:char **ppch
),根据我的理解,它们可以用作二维数组,因为 char *pch
,例如可以作为char
/string
.
是这样还是我漏掉了什么?我不确定我们如何在程序中使用 P2P,或者我的理解是否接近正确。
有人可以举个例子吗?我们是否需要为这些 P2P 中的每个元素分配 malloc()
的内存?
数组的固有特性属性是,它们的元素在内存中是连续的。例如
int foo[] = { 1, 2, 3, 4, 5, /* ... */ };
// ~> 1, 2, 3, 4, 5, ...
二维数组也不例外:
int bar[][3] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
// ~> 1, 2, 3, 4, 5, 6, 7, 8, 9
但是指向某种类型指针的指针
int **qux;
就是这样。指向一个指针(或多个指针)的指针。当你分配内存时
int **qux = malloc(N * sizeof(*qux));
你得到一个指向内存区域的指针,该内存区域的大小足以容纳 N
指向 int
的指针,后者又可以指向其他内存区域:
int **qux = malloc(N * sizeof(*qux));
int value = 0;
for (size_t i = 0; i < N; ++i) {
qux[i] = malloc(P * sizeof(**qux));
for (size_t k = 0; k < P; ++k)
qux[i][k] = ++value;
}
在记忆中看起来像
+----------+ +-----+
| qux[0] --|------------------------------|-> 1 |
| qux[1] --|-----------+ | 2 |
| qux[2] --|---+ | +-----+ | 3 |
| ... | | +-------|-> 4 | +-----+
+----------+ | | 5 |
| +-----+ | 6 |
+----|-> 7 | +-----+
| 8 |
| 9 |
+-----+
所以不,指向指针的指针不是二维数组。像这样的东西更像是 "jagged array".
至于你的字符串示例,没有区别:
char **qux; // a pointer to a (number of) pointers to char
qux = malloc(N * sizeof(*foo));
// just an array to fill the memory qux points to with:
char const *source[] = { "foo", "bar", "baz", "qux" /* I'm running out of names */ };
size_t index = 0;
for (size_t i = 0; i < N; ++i) {
qux[i] = malloc((strlen(source[index]) + 1) * sizeof(**qux));
strcpy(qux[i], source[index++]);
}
~>
+----------+ +--------+
| foo[0] --|------------------------------------------------------|-> 'f' |
| foo[1] --|-----------------------------------+ | 'o' |
| foo[2] --|----------------------+ | +--------+ | 'o' |
| foo[3] --|---+ | +----|-> 'b' | | '[=17=]' |
| ... | | | | 'a' | +--------+
+----------+ | +--------+ | +--------+ | 'r' |
+----|-> 'q' | +---|-> 'b' | | '[=17=]' |
| 'u' | | 'a' | +--------+
| 'x' | | 'z' |
| '[=17=]' | | '[=17=]' |
+--------+ +--------+
相比之下,char
s 的真实二维数组:
char foo[][4] = { "foo", "bar", "baz", "qux" /*, ... */ };
// ~> 'f', 'o', 'o', '[=18=]', 'b', 'a', 'r', '[=18=]', 'b', 'a', 'z', '[=18=]', 'q', 'u', 'x', '[=18=]', ...