3

次のような 3 次元配列へのポインターがあります。

char ***_cube3d

そして、私は次のように初期化しています:

_cube3d = (char ***)malloc(size * (sizeof(char**)));
for (int i = 0; i< size; i++) {
    _cube3d[i] = (char **)malloc(size * sizeof(char*));
    for (int j = 0; j<size; j++) {
        _cube3d[i][j] = (char *)malloc(size * sizeof(char));
    }
}

配列は動的なサイズであり、数千の要素を含めることができるため、事前に配列として宣言することはできません。

ここで、すべての内容を別の配列にできるだけ効率的にコピーしたいと考えています。各要素を 1 つずつコピーするネストされたループ ソリューションは知っていますが、非常に非効率的です。このプロセスをスピードアップする方法はありますか? C++ コードは大歓迎ですが、私はこのソリューションを Objective C に繰り返すことを計画しており、C++ コードをクリーンな Objective C プロジェクトに挿入することは避けたいので、単純な C での使用を好みます。

誰かが私を正しい方向に向けることができますか?

4

3 に答える 3

3

すでに持っているものを使用します(ただし、最初のものは で修正mallocしますsizeof(char***)

次のような一連の for ループを実行することで、配列をコピーできます。

char new_cube[side][side][side];
for(unsigned int x = 0; x < side; x++)
    for(unsigned int y = 0; y < side; y++)
        for(unsigned int z = 0; z < side; z++)
            new_cube[x][y][z] = old_cube[x][y][z];

また:

char new_cube[side][side][side];
for(unsigned int x = 0; x < side; x++)
    for(unsigned int y = 0; y < side; y++)
        memcpy(new_cude[x][y], old_cube[x][y], sizeof(char)*side);

これは少し速いかもしれません。

この方法を使用すると、c++ の使用を避けることができ (希望どおり)、コードの複雑さが最小限に抑えられます。

于 2013-10-31T00:18:05.737 に答える
2

C.99 を使用している場合は、可変長配列 (VLA) を使用して 3 次元配列を動的に割り当てることができます。が決定されたらside、ポインタを次のように宣言できます。

char (*cube3d_)[side][side];

そして、次のように初期化します。

cube3d_ = malloc(side * sizeof(*cube3d_));

C では、 の戻り値をキャストする必要はありません。キャストするmalloc()と、最悪の場合、未定義の動作が実際に発生する可能性があることに注意してください。「キューブ」は連続したブロックとして割り当てられているので、 でコピーできますmemcpy()

C++ には VLA がありません。a を使用しvectorて、マルチ動的割り当て構造に相当する C++ を取得できます。

std::vector<std::vector<std::vector<char> > >
cube3d_(side, std::vector<std::vector<char> >(side, std::vector<char>(side)));

その後、コピー コンストラクターまたは代入を使用してコピーできます。


がオブジェクト/構造体のメンバー変数である場合cube3d_、オブジェクトが の値を認識している限りside、VLA ポインターを使用してメモリにアクセスできます。例えば:

struct Obj {
    size_t side_;
    void *cube3d_;
};

//...
size_t side = 3;

//...
Obj o;
o.side_ = side;
char (*p)[o.side_][o.side_] = malloc(o.side_ * sizeof(*p));
o.cube3d_ = p;

//...
char (*q)[o.side_][o.side_] = o.cube3d_;
q[1][2][2] = 'a';
于 2013-10-31T00:07:57.010 に答える
1

これは、C と構造体を使用して、一連のヘルパー関数と共にある程度のオブジェクト指向を提供するアプローチです。

ここでのアイデアは、連続した配列に関する Kerrick の提案を使用することでした。

オフセット計算が正しいかどうかはわかりませんし、テストもされていないので、あなたが支払っている金額に見合うだけの価値があります. ただし、出発点としては役立つ場合があります。

アイデアは、メモリ管理を容易にするために、単一の連続したメモリ領域を持つことです。また、関数を使用して、x、y、および z 方向のゼロベースのオフセットを使用して特定の要素にアクセスします。そして、要素のサイズ/タイプがよくわからなかったので、それも変数にしました。

#include <malloc.h>

typedef struct _Array3d {
    int   elSize;     // size of each element of the array in bytes
    int   side;       // length of each side of the 3d cube in elements
    char  * (*Access) (struct _Array3d *pObj, int x, int y, int z);
    char  buffer[1];
} Array3d;

static  char * Array3d_Access (Array3d *pObj, int x, int y, int z)
{
    char *pBuf = NULL;

    if (pObj && x < pObj->side && y < pObj->side && z < pObj->side) {
        pBuf = &(pObj->buffer[x * pObj->side * pObj->elSize * pObj->side * pObj->elSize + y * pObj->side * pObj->elSize + z * pObj->elSize]);
    }

    return pBuf;
}

// Create an Array3d cube by specifying the length of each side along with the size of each element.
Array3d *Array3d_Factory (int side, int elSize)
{
    Array3d *pBuffer = malloc (sizeof(Array3d) + side * elSize * side * elSize * side * elSize);

    if (pBuffer) {
        pBuffer->elSize = elSize;
        pBuffer->side = side;
        pBuffer->Access = Array3d_Access;
    }

    return pBuffer;
}

// Create an Array3d cube that is the same size as an existing Array3d cube.
Array3d *Array3d_FactoryObj (Array3d *pObj)
{
    Array3d *pBuffer = NULL;

    if (pObj) {
        int     iBufferSize = pObj->side * pObj->elSize * pObj->side * pObj->elSize * pObj->side * pObj->elSize;

        pBuffer = malloc (sizeof(Array3d) + iBufferSize);
        if (pBuffer) {
            pBuffer->elSize = pObj->elSize;
            pBuffer->side = pObj->side;
            pBuffer->Access = pObj->Access;
        }
    }

    return pBuffer;
}

// Duplicate or clone an existing Array3d cube into new one.
// Returns NULL if cloning did not happen.
Array3d *Array3d_Dup (Array3d *pObjDest, Array3d *pObjSrc)
{
    if (pObjSrc && pObjDest && pObjSrc->elSize == pObjDest->elSize && pObjSrc->side == pObjDest->side) {
        int     iBufferSize = pObjSrc->side * pObjSrc->elSize * pObjSrc->side * pObjSrc->elSize * pObjSrc->side * pObjSrc->elSize;

        memcpy (pObjDest->buffer, pObjSrc->buffer, iBufferSize);
    } else {
        pObjDest = NULL;
    }

    return pObjDest;
}

int main(int argc, _TCHAR* argv[])
{
    Array3d *pObj = Array3d_Factory (10, 20 * sizeof(char));

    char *pChar = pObj->Access (pObj, 1, 2, 3);
    return 0;
}
于 2013-10-31T00:46:41.157 に答える