简体   繁体   English

C复制三维数组

[英]C copy 3-dimensional array

I have a pointer to a 3-dimensional array, like this: 我有一个指向三维数组的指针,如下所示:

char ***_cube3d

And I am initialising it like this: 我正在初始化它:

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

Note that the array is of dynamic size, and can contain thousands of elements, so we cannot declare it as an array in advance. 请注意,该数组具有动态大小,并且可以包含数千个元素,因此我们不能提前将其声明为数组。

Now, I want to copy all of its contents into another array, as efficiently as possible. 现在,我希望尽可能高效地将其所有内容复制到另一个数组中。 I know the nested loop solution where we copy each element one by one, however, it seems extremely inefficient to me. 我知道嵌套循环解决方案,我们逐个复制每个元素,但是,对我来说这似乎是非常低效的。 Is there a way to speed this process up? 有没有办法加快这个过程? C++ code is welcome, although I would prefer it in plain C, since I am planning to iterate this solution into Objective C, and I would like to avoid injecting C++ code into a clean Objective C project. C ++代码是受欢迎的,虽然我更喜欢它在普通的C中,因为我打算将这个解决方案迭代到Objective C,我想避免将C ++代码注入一个干净的Objective C项目。

Can anyone point me in the right direction? 谁能指出我正确的方向?

Using what you already have (but fixing the first malloc with sizeof(char***) ) 使用你已经拥有的东西(但用sizeof(char***)修复第一个malloc

You could copy the array by running a bunch of for loops like this: 您可以通过运行一堆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];

OR: 要么:

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

which might be a bit faster. 这可能会快一点。

using this method you avoid using any c++(as you said you would like) and your code complexity is kept minimal. 使用此方法可以避免使用任何c ++(正如您所说的那样),并且您的代码复杂性保持最小。

If you are using C.99, you can use a variable length array (VLA) to dynamically allocate your 3-dimensional array. 如果您使用的是C.99,则可以使用可变长度数组(VLA)动态分配3维数组。 Once side is determined, you can declare your pointer to be: 一旦确定了side ,您可以将指针声明为:

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

And then initialize it like this: 然后像这样初始化它:

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

Note that in C, you are not required to cast the return value of malloc() , and doing so can actually lead to undefined behavior in the worst case. 请注意,在C中,您不需要malloc()的返回值,这样做实际上可能导致最坏情况下的未定义行为。 Since the "cube" has been allocated as a contiguous block, it can be copied with memcpy() . 由于“立方体”已被分配为连续块,因此可以使用memcpy()进行复制。

C++ does not have VLA. C ++没有VLA。 You can use a vector to get the C++ equivalent of your multi-dynamic allocation structure: 您可以使用vector来获得与多动态分配结构相当的C ++:

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

You can then copy it using a copy constructor or an assignment. 然后,您可以使用复制构造函数或赋值来复制它。


If cube3d_ is a member variable of an object/structure, so long as your object knows the value of side , you can still use a VLA pointer to access the memory. 如果cube3d_是对象/结构的成员变量,只要您的对象知道side的值,您仍然可以使用VLA指针来访问内存。 For example: 例如:

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';

Here is an approach using C and structs to provide some degree of object oriented along with a set of helper functions. 这是一种使用C和结构来提供某种程度的面向对象以及一组辅助函数的方法。

The idea here was to use Kerrick's suggestion of a contiguous array. 这里的想法是使用Kerrick建议的连续数组。

I am not sure if I got the offset calculation correct and it has not been tested so it is worth what you are paying for it. 我不确定我是否得到了正确的偏移计算,并且尚未经过测试,因此值得为此付出代价。 However it may be helpful as a starting place. 然而,作为起点可能会有所帮助。

The idea is to have a single contiguous area of memory to make memory management easier. 我们的想法是拥有一个连续的内存区域,以便更轻松地进行内存管理。 And to use a function to access a particular element using a zero based offset in the x, y, and z directions. 并使用函数在x,y和z方向上使用基于零的偏移来访问特定元素。 And since I was not sure as to the element size/type, I made that a variable as well. 由于我不确定元素大小/类型,我也将其作为变量。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM