如何在预先分配的内存上指向2D / 3D空间

我内存优化了我用于嵌入式使用的代码。 它运行良好,但结果是我获得了大量的1D,2D和3D mallocs,并在函数中间释放,从而减慢了执行时间。

出于几个原因,我决定修改我的方式。 我想在执行开始时用一个malloc分配所有可用的内存,并指出每个数组需要的正确内存空间。

有关信息,我现在在x86上执行此操作,所以我没有任何内存空间问题。 我用这种方式声明我的数组:

unsigned char *memory; memory = (unsigned char *)malloc(MYSIZE*sizeof(unsigned char)); type* p1; p1 = (type *)((int)memory + p1_offset); type** p2; p2 = (type **)((int)memory + p2_offset); for (int i=0 ; i<p2_height ; i++) { p2[i] = (type *)((int)p2 + p2_width*sizeof(type)); } 

虽然它适用于我的1D指针,但它为我的2D指针声明返回了一个段错误。 我检查了我的偏移量,它们与内存指针相比很好。 由于我没有经验这种方式来宣布我的指针,也许我在这里误解了一些东西,所以如果有人可以向我解释更多关于这种技术的话,我会很高兴!

您将p2声明为指向指针数组的指针,而不是指向平面二维数组的指针。 你也是(编辑为了清晰:)用垃圾整数初始化p2 ,然后将它转换回指针并解除引用它。

编辑添加示例代码:

 #include  #include  #include  #include  /* Boilerplate to turn this into a MWE: */ #define MYSIZE 1024U typedef double elem_t; static const size_t p1_offset = 0, p2_offset = 512; /* Our buffer will hold W 1d elements and X*Y 2d elements. */ #define W 64U #define X 32U #define Y 2U typedef struct { elem_t array1[W]; elem_t array2[X][Y]; } spaces_t; /* Test driver: */ int main(void) { /* sizeof(unsigned char) is defined as 1. Do you mean to allocate an * array of MYSIZE bytes or MYSIZE elements of type? */ spaces_t * const memory = malloc(sizeof(spaces_t)); if (!memory) { perror("malloc"); exit(EXIT_FAILURE); } elem_t* p1 = memory->array1; elem_t* p2 = (elem_t*)(memory->array2); /* Never cast a pointer to int. It's not even legal. * Why does this assertion succeed? Why are memory and bad_idea * equal, but memory+1 and bad_idea+1 different by the size of both * of our arrays combined, minus one byte? */ const uintptr_t bad_idea = (uintptr_t)memory; assert( (uintptr_t)(memory+1) - (bad_idea+1) == sizeof(spaces_t) - 1 ); /* Let's initialize all the arrays. No segfaults? */ size_t i,j; for (i = 0; i < W; ++i) { *p1 = (elem_t)i; assert( memory->array1[i] == *p1 ); ++p1; } /* This is a lot faster when X is a power of 2: */ for (i = 0; i < X; ++i) for ( j = 0; j < Y; ++j) { *p2 = (elem_t)(100*i + j); assert( memory->array2[i][j] == *p2 ); ++p2; } return EXIT_SUCCESS; } 

问题是type** p2; 是指向指针的指针,它与2D数组无关。

相反,声明一个指向2D数组的指针:

 type (*p2)[x][y]; 

如果您不想将2D数组取消引用为(*p2)[i][j] ,那么只需在声明中删除最里面的维度:

 type (*p2)[y]; 

现在您可以将2D数组取消引用为p2[i][j] 。 这个技巧有效,因为p2[i]根据指向的类型(j类型项的数组p2[i]给出指针算法,与任何其他指针相同。


从指针到(signed)int的转换也是模糊和不安全的。 对于执行此操作的代码中的每个案例,保留char类型,计算偏移量,然后将其转换为(void*) 。 例:

 p2 = (void*)(memory + p2_offset);