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));
    }
}

请注意,数组是动态大小的,可以包含数千个元素,因此我们不能提前将其声明为数组。

现在,我想尽可能高效地将其所有内容复制到另一个数组中。我知道嵌套循环解决方案,我们一个一个地复制每个元素,但是,它对我来说似乎效率极低。有没有办法加快这个过程?欢迎使用 C++ 代码,尽管我更喜欢使用纯 C 语言,因为我计划将此解决方案迭代到 Objective C 中,并且我想避免将 C++ 代码注入到干净的 Objective 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。您可以使用 avector来获得多动态分配结构的 C++ 等价物:

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

然后,您可以使用复制构造函数或赋值来复制它。


Ifcube3d_是对象/结构的成员变量,只要您的对象知道 的值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 回答