2010-02-12 2 views
1

Я пытаюсь создать непрерывный блок памяти в одном вызове функции, который имеет первую часть памяти в виде указательных массивов для других блоков. В основном, я пытаюсь сделать:Смежный блок памяти с malloc

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

Но с одним блоком. Это, насколько я получил:

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

ответ

1

Что-то вроде этого

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; 
} 
+0

Я думаю, что получаю ваш ответ, но у меня возникают проблемы с идеей выделения памяти для указателей строк и столбцов. Итак, с этим блоком памяти, cb, вы можете просто приписать часть pmem, чтобы разделить его? Как первая часть, являющаяся указателями на указатели, тогда pcol указывает на указатель последней строки, затем инициализирует cols и имеет указатель на указатели, указывающие на pcol? Что-то вроде того? – Crystal

+1

да. Вы выделяете общее количество, затем используйте указатель math для получения указателя pcol по первому адресу _after_ той части, которую вы хотите назначить для новичков, затем пройдите указатель pcol и используйте его для инициализации массива промахов. конечным результатом является одно выделение, но с тем же расположением, что и исходный код. –

+0

@Crystal: еще раз проверьте код, у меня была ошибка в цикле. Прости. –

0

Я не слишком ясно, о том, что вы пытаетесь сделать, но ваш последний кусок кода ошибки. Вы проверяете arrayPtr на NULL, но никогда не назначаете его. В цикле for() вы назначаете arrayPtr, но на самом деле ничего не делаете с ним.

Если вы ищете массив 2D, который использует один блок памяти, то, что случилось с:

int* array = (int*)malloc(rows * count * sizeof(int)); 
int* someCellPtr = &array[y * rows + x]; 

?

0

если вы хотите 2D массив с одним Alloc, вы можете использовать либо calloc:

int** p2DArray = (int**)calloc(rows,cols * sizeof(int)); 

или просто таНос:

int** p2DArray = (int**)malloc(rows * cols * sizeof(int)); 

это позволяет нормальную индексацию:

int nCellValue = p2DArray[row][col]; 
int* pCell = &p2DArray[row][col]; 
1

Похоже, что у вас нет четкого представления о том, чего вы хотите достичь . Документ! Это очистит ваш разум, и, кроме того, если вы этого не поймете, никто не будет, и код, подобный этому, - это кошмар для поддержания (применяется даже к вашим собственным, когда проходит время ).

Чтобы создать функцию, которая выделяет непрерывный блок памяти, вы должны вызывать SafeMalloc только один раз с общим объемом памяти, который будет использоваться.

/* 
* 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; 
} 

Этот пример основан на сохранении как можно ближе к оригиналу, насколько это возможно, ответ Джона Knoeller путем использования подписки массива, вероятно, лучший способ сделать это.

Смежные вопросы