[英]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.