I'm trying to create a contiguous block of memory in one function call that has the first part of the memory as pointer arrays to the other blocks. Basically, I'm trying to do:
int **CreateInt2D(size_t rows, size_t cols)
{
int **p, **p1, **end;
p = (int **)SafeMalloc(rows * sizeof(int *));
cols *= sizeof(int);
for (end = p + rows, p1 = p; p1 < end; ++p1)
*p1 = (int *)SafeMalloc(cols);
return(p);
}
void *SafeMalloc(size_t size)
{
void *vp;
if ((vp = malloc(size)) == NULL) {
fputs("Out of mem", stderr);
exit(EXIT_FAILURE);
}
return(vp);
}
B开发者_如何学运维ut with one block. This is as far as I've gotten:
int *Create2D(size_t rows, size_t cols) {
int **memBlock;
int **arrayPtr;
int loopCount;
memBlock = (int **)malloc(rows * sizeof(int *) + rows * cols * sizeof(int));
if (arrayPtr == NULL) {
printf("Failed to allocate space, exiting...");
exit(EXIT_FAILURE);
}
for (loopCount = 1; loopCount <= (int)rows; loopCount++) {
arrayPtr = memBlock + (loopCount * sizeof(int *));
//I don't think this part is right. do I need something like arrayPtr[loopCount] = ....
}
return(memBlock);
}
Something like this
int **Create2D(size_t rows, size_t cols)
{
size_t cb = (rows * sizeof(int *)) + (rows * cols * sizeof(int));
int * pmem = (int *)SafeMalloc(cb);
int ** prows = (int **)pmem;
int * pcol = (int *)&prows[rows]; // point pcol after the last row pointer
for (int ii = 0; ii < rows; ++ii)
{
prows[ii] = pcol;
pcol += cols;
}
return prows;
}
It seems that you do not have a clear picture of exactly what you want to achieve. Document it! It will clear up your mind and besides if you do not understand it, nobody else will, and code like that is a nightmare to maintain (applies even to your own when time passes by).
To create a function that allocates a contiguous block of memory, you have to call SafeMalloc only once with the total amount of memory that will be used.
/*
* Memory layout example for 2 rows and 3 cols
*
* 1 1 1 1 1 1 1 1 1 1
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |P|P|C|C|C|C|C|C|C|C|C|C|C|C|C|C|C|C|C|C|
* |1|2|1|1|1|2|2|2|3|3|3|1|1|1|2|2|2|3|3|3|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* P1 is a pointer coloum data for row 1, points to memory start + offset 2 (assuming sizeof(int) == sizeof(int *))
* P2 is for row 2, points to memory start + offset 11
* C1 is coloumn 1 data, etc
*/
int **CreateInt2D(size_t rows, size_t cols)
{
int **memory_start, **p1, *col_data;
size_t total_memory_to_allocate;
total_memory_to_allocate = rows * sizeof(int *) + rows * cols * sizeof(int);
memory_start = (int **) SafeMalloc(total_memory_to_allocate);
for (col_data = (int *)(memory_start + rows), p1 = memory_start;
p1 < (int **)col_data;
++p1, col_data += cols * sizeof(int))
*p1 = col_data;
return memory_start;
}
This example is based on keeping as close to your original as possible, John Knoeller's answer by using array subscription is probably a better way of doing it.
I'm not too clear about what you're trying to do, but your last piece of code is buggy. You test arrayPtr against NULL but never assign it. In the for() loop you assign to arrayPtr but don't actually do anything with it.
If you are looking for a 2D array that uses a single block of memory then what's wrong with:
int* array = (int*)malloc(rows * count * sizeof(int));
int* someCellPtr = &array[y * rows + x];
?
if you want to 2D array with one alloc, you can either use calloc:
int** p2DArray = (int**)calloc(rows,cols * sizeof(int));
or just malloc:
int** p2DArray = (int**)malloc(rows * cols * sizeof(int));
this allows normal indexing:
int nCellValue = p2DArray[row][col];
int* pCell = &p2DArray[row][col];
精彩评论