當你有一個指針指向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個(再次連續)第一個int
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(...);
以上...
是我們想要的i
個數據的大小。它可能是一個常量,或者它可能是一個變量,取決於i
,或者月亮的階段,或隨機數或其他任何東西。要注意的要點是,你在循環中調用malloc()
,並且雖然每個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 char
s。但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()
爲分配內存3210,那麼你將需要一個循環來複制所有的數據。
這完全取決於你的「多維數組」是如何構建的。顯示創建它的代碼。 – caf 2010-02-09 00:17:52
如果你沒有數組維度,那麼你也不能用循環複製它。 – 2010-02-09 00:30:29
@John Knoeller:謝謝。我已經更新了描述。 – dan 2010-02-09 00:33:26