Перераспределение смежных 2D-массивов

Я создаю непрерывные 2d массивы, используя метод, опубликованный здесь Шон Чин. [1] [2] Он работает очень хорошо.

Коротко от его поста:

char** allocate2Dchar(int count_x, int count_y) { int i; # allocate space for actual data char *data = malloc(sizeof(char) * count_x * count_y); # create array or pointers to first elem in each 2D row char **ptr_array = malloc(sizeof(char*) * count_x); for (i = 0; i < count_x; i++) { ptr_array[i] = data + (i*count_y); } return ptr_array; } 

И следующая свободная функция:

 void free2Dchar(char** ptr_array) { if (!ptr_array) return; if (ptr_array[0]) free(ptr_array[0]); free(ptr_array); } 

Для меня не очевидно, как создать эквивалентную функцию перераспределения в любом измерении, хотя меня интересует только перераспределение количества строк при сохранении непрерывности. Растущее количество столбцов было бы интересно понять, но, вероятно, довольно сложно. Я не нашел прямого обсуждения этой проблемы где угодно, кроме как сказать: «Это сложно!». [2]

Конечно, это можно выполнить с помощью ужасного метода грубой силы, скопировав данные в новый 1D-массив (данные, выше) для хранения, перераспределяя 1D-массив, а затем освобождая и регенерируя указатели (ptr_array) к элементам строки для новый размер. Это, однако, довольно медленно для модификации строк, так как необходимо, по крайней мере, удвоить потребность в памяти для копирования данных, и это действительно ужасно плохо для изменения количества столбцов.

Это пример указанного метода для изменения количества строк (он не будет работать должным образом для изменения количества столбцов, поскольку смещения для указателей будут неправильными для данных). Я не полностью протестировал это, но вы поняли …

 double ** reallocate_double_array (double **ptr_array, int count_row_old, int count_row_new, int count_col) { int i; int old_size = count_row_old * count_col; int new_size = count_row_new * count_col; double *data = malloc (old_size * sizeof (double)); memcpy (&data[0], &ptr_array[0][0], old_size * sizeof (double)); data = realloc (data, new_size * sizeof (double)); free (ptr_array[0]); free (ptr_array); ptr_array = malloc (count_row_new, sizeof (double *)); for (i = 0; i < count_row_new; i++) ptr_array[i] = data + (i * count_col); return ptr_array; } 

Кроме того, этот метод требует, чтобы вы знали предыдущий размер, что является неприятным!

Любые мысли очень оценили.

[1] Как я могу выделить 2D-массив, используя двойные указатели?

[2] http://www.eng.cam.ac.uk/help/tpl/languages/C/teaching_C/node52.html

Первый malloc и memcpy не нужны, потому что у вас есть легкий доступ к исходному массиву данных в ptr_array[0] . Вам не нужно знать старый размер, потому что realloc должен помнить, сколько он выделил по адресу и переместил правильный объем данных.

Что-то вроде этого должно работать.

 double ** reallocate_double_array (double **ptr_array, int count_row_new, int count_col) { int i; int new_size = count_row_new * count_col; double *data = ptr_array[0]; data = realloc (data, new_size * sizeof (double)); free (ptr_array); ptr_array = calloc (count_row_new, sizeof (double *)); for (i = 0; i < count_row_new; i++) ptr_array[i] = data + (i * count_col); return ptr_array; }