2D Cスタイルの配列は一般的に残念ですが、紙の上でシンプルで便利ですが、動的メモリ管理の実装 - 割り当ての失敗やクリーンアップ/サイズ変更の処理 - はしばしば詳細が難しい。これらのアプローチの大きな問題は、クリーンアップが厄介であることは通常あり
/*
* Start with an array that can hold INITIAL_NUM elements of (char*).
*/
char **aList = (char**)malloc(INITIAL_NUM, sizeof(*aList));
int curIdx = 0, curListSz = INITIAL_NUM;
while (more_stuff_to_append) {
/*
* Still space in the existing list ? If not - resize
*/
if (curIdx >= INITIAL_NUM) {
curListSz += ALLOC_INCREMENT_FOR_ALIST;
if ((aList = realloc(aList, curListSz * sizeof(*aList))) == NULL)
error_and_yucky_cleanup("can't resize list, out of memory");
}
/*
* Allocate a new element.
* Note that if it's _known_ in advance that all elements
* are the same size, then malloc'ing a big block and slicing
* that into pieces is more efficient.
*/
if ((aList[curIdx] = malloc(new_elem_size, sizeof(char)) == NULL)
error_and_yucky_cleanup("out of memory");
/*
* put the contents into the new buffer, however that's done.
*/
populate_new_entry(aList[curIdx]);
curIdx++;
}
:あなたは何ができるか
のようなものです。配列内を移動してすべての要素に対してfree()を呼び出し、最後にaList
をクリーンアップする必要があります。
すべてのサイズを事前に知っていれば、のメモリブロックを割り当てて、aList
とすべての要素を保持することができます。このようなものを経由して動作します:
#define LISTSZ(lst) (NUMSTRINGS_MAX * sizeof(*(lst)))
#define ELEMSZ(lst) (STRINGSIZE_MAX * sizeof(**(lst)))
char **aList = malloc(LISTSZ(aList) + NUMSTRINGS * ELEMSZ(aList));
char *curElem = ((char*)aList) + LISTSZ(aList));
int i;
for (i = 0; i < NUMSTRINGS_MAX; i++) {
aList[i] = curElem;
curElem += ELEMSZ(aList);
}
この利点は、クリーンアップが些細なことである - ちょうどfree((char*)aList);
を呼び出し、全体のことを行っています。しかし、メモリブロックの先頭に新しいスペースを挿入しないようにすると(aList[]
が格納されているため)、realloc()
をもう使用できなくなります。
これらのことは、C++ベクタを使用するための本当の理由を構成します。少なくともC++は自動的にクリーンアップ(メモリ不足例外など)を自動的に行います。
これが基本的な質問である場合、既にサイト上にあるc(または時にはC++)の多次元動的配列に関する多くの質問があります。この検索を試してください:http://stackoverflow.com/search?q=[c]+multi+dimension+array。 – dmckee