当你有一个指向 C 中的指针的指针时,你必须知道数据将如何被使用并在内存中布局。现在,第一点很明显,对于任何变量来说都是如此:如果您不知道某个变量将如何在程序中使用,为什么要使用它? :-)。第二点比较有意思。
在最基本的层面上,指向T 类型的指针指向T 类型的一个 对象。例如:
int i = 42;
int *pi = &i;
现在,pi 指向一个 int。如果您愿意,可以将指针指向许多此类对象中的第一个:
int arr[10];
int *pa = arr;
int *pb = malloc(10 * sizeof *pb);
pa 现在指向 10 个(连续)int 值序列中的第一个,假设 malloc() 成功,pb 指向另一组 10 个(再次,连续)@ 中的第一个987654331@s.
如果你有一个指向指针的指针,这同样适用:
int **ppa = malloc(10 * sizeof *ppa);
假设malloc() 成功,现在您有ppa 指向10 个连续int * 值序列中的第一个。
所以,当你这样做时:
char **tmp = malloc(sizeof(char *)*CR_MULTIBULK_SIZE);
tmp 指向CR_MULTIBULK_SIZE 此类对象序列中的第一个char * 对象。上面的每个指针都没有初始化,所以tmp[0]到tmp[CR_MULTIBULK_SIZE-1]都包含垃圾。初始化它们的一种方法是malloc()它们:
size_t i;
for (i=0; i < CR_MULTIBULK_SIZE; ++i)
tmp[i] = malloc(...);
上面的... 是我们想要的ith 数据的大小。它可以是一个常数,也可以是一个变量,这取决于i、月相、随机数或其他任何东西。需要注意的主要一点是,您在循环中对malloc() 进行了CR_MULTIBULK_SIZE 调用,并且虽然每个malloc() 将返回一个连续的内存块,但malloc() 调用之间的连续性并不能保证。换句话说,第二个malloc() 调用不能保证返回一个指针,该指针从前一个malloc() 的数据结束处开始。
为了更具体,我们假设CR_MULTIBULK_SIZE 是 3。在图片中,您的数据可能如下所示:
+------+ +---+---+
tmp: | |--------+ +----->| a | 0 |
+------+ | | +---+---+
| |
| |
| +------+------+------+
+-------->| 0 | 1 | 2 |
+------+------+------+
| |
| | +---+---+---+---+---+
| +--->| t | e | s | t | 0 |
+------+ +---+---+---+---+---+
|
|
| +---+---+---+
+--->| h | i | 0 |
+---+---+---+
tmp 指向一个由 3 个 char * 值组成的连续块。第一个指针tmp[0] 指向一个由3 个char 值组成的连续块。同样,tmp[1] 和 tmp[2] 分别指向 5 和 2 chars。但是tmp[0]指向tmp[2]的内存整体上并不连续。
由于memcpy()复制的是连续的内存,你想做的事一个memcpy()是做不到的。此外,您需要知道每个tmp[i] 是如何分配的。所以,一般来说,你想做的事情需要一个循环:
char **realDest = malloc(CR_MULTIBULK_SIZE * sizeof *realDest);
/* assume malloc succeeded */
size_t i;
for (i=0; i < CR_MULTIBULK_SIZE; ++i) {
realDest[i] = malloc(size * sizeof *realDest[i]);
/* again, no error checking */
memcpy(realDest[i], tmp[i], size);
}
如上所述,您可以在循环内调用memcpy(),因此您的代码中不需要嵌套循环。 (很可能memcpy() 是用循环实现的,所以效果就像你有嵌套循环一样。)
现在,如果你有这样的代码:
char *s = malloc(size * CR_MULTIBULK_SIZE * sizeof *s);
size_t i;
for (i=0; i < CR_MULTIBULK_SIZE; ++i)
tmp[i] = s + i*CR_MULTIBULK_SIZE;
即,您在一个 malloc() 调用中为所有指针分配了连续空间,然后您可以在代码中复制所有数据而无需循环:
size_t i;
char **realDest = malloc(CR_MULTIBULK_SIZE * sizeof *realDest);
*realDest = malloc(size * CR_MULTIBULK_SIZE * sizeof **realDest);
memcpy(*realDest, tmp[0], size*CR_MULTIBULK_SIZE);
/* Now set realDest[1]...realDest[CR_MULTIBULK_SIZE-1] to "proper" values */
for (i=1; i < CR_MULTIBULK_SIZE; ++i)
realDest[i] = realDest[0] + i * CR_MULTIBULK_SIZE;
从上面,简单的答案是,如果您有多个malloc() 为tmp[i] 分配内存,那么您将需要一个循环来复制所有数据。