Использование malloc для размещения многомерных массивов с разной длиной строк

У меня есть следующий код:

 int *a; size_t size = 2000*sizeof(int); a = (int *) malloc(size); 

который отлично работает. Но если у меня есть следующее:

 char **b = malloc(2000*sizeof *b); 

где каждый элемент из b имеет разную длину.

Как можно сделать то же самое для b как и для a ; т.е. следующий код будет корректным?

 char *c; size_t size = 2000*sizeof(char *); c = (char *) malloc(size); 

Во-первых, вам нужно выделить массив указателей, таких как char **c = malloc( N * sizeof( char* )) , затем распределить каждую строку с помощью отдельного вызова malloc , возможно, в цикле:

 /* N is the number of rows */ /* note: c is char** */ if (( c = malloc( N*sizeof( char* ))) == NULL ) { /* error */ } for ( i = 0; i < N; i++ ) { /* x_i here is the size of given row, no need to * multiply by sizeof( char ), it's always 1 */ if (( c[i] = malloc( x_i )) == NULL ) { /* error */ } /* probably init the row here */ } /* access matrix elements: c[i] give you a pointer * to the row array, c[i][j] indexes an element */ c[i][j] = 'a'; 

Если вы знаете общее количество элементов (например, N*M ), вы можете сделать это в одном распределении.

Типичная форма для динамического распределения массива NxM типа T

 T **a = malloc(sizeof *a * N); if (a) { for (i = 0; i < N; i++) { a[i] = malloc(sizeof *a[i] * M); } } 

Если каждый элемент массива имеет разную длину, то замените M соответствующей длиной для этого элемента; например

 T **a = malloc(sizeof *a * N); if (a) { for (i = 0; i < N; i++) { a[i] = malloc(sizeof *a[i] * length_for_this_element); } } 

Эквивалентное распределение памяти для char a[10][20] будет следующим.

 char **a; a=(char **) malloc(10*sizeof(char *)); for(i=0;i<10;i++) a[i]=(char *) malloc(20*sizeof(char)); 

Надеюсь, это выглядит просто, чтобы понять.

Другим подходом было бы выделение одного непрерывного fragmentа памяти, содержащего блок заголовка для указателей на строки, а также блок тела для хранения фактических данных в строках. Затем просто выделите память, назначив адреса памяти в теле указателям в заголовке на каждой строке. Это будет выглядеть следующим образом:

 int** 2dAlloc(int rows, int* columns) { int header = rows * sizeof(int*); int body = 0; for(int i=0; i 

Преимуществом этого подхода является элегантное освобождение памяти и возможность использовать напоминающую массив опознавание для доступа к элементам результирующего 2D-массива.

Если каждый элемент из b имеет разную длину, вам нужно сделать что-то вроде:

 int totalLength = 0; for_every_element_in_b { totalLength += length_of_this_b_in_bytes; } return (char **)malloc(totalLength); 

Я думаю, что двухступенчатый подход лучше, потому что c 2-d массивы – это просто массивы массивов. Первым шагом является выделение одного массива, а затем цикл его распределения массивов для каждого столбца, когда вы идете. Эта статья дает хорошие подробности.

malloc не выделяет на определенных границах, поэтому следует предположить, что он выделяет границу байта.

Возвращенный указатель затем не может использоваться, если преобразован в любой другой тип, поскольку доступ к этому указателю, вероятно, приведет к нарушению доступа к памяти CPU, и приложение будет немедленно отключено.

Распределение динамической памяти массива 2-D

 int **a,i; // for any number of rows & columns this will work a = (int **)malloc(rows*sizeof(int *)); for(i=0;i 
  • Общие правила передачи / возврата ссылки на массив (не указатель) на / из функции?
  • Объединение двух массивов в .NET.
  • Как проверить, находится ли элемент в массиве
  • Проверяет ли foreach массив на каждой итерации?
  • Что делает объект jQuery отображаться как массив в инструментах разработчика Chrome?
  • Генерики, массивы и ClassCastException
  • Могу ли я взять адрес элемента «один конец прошлого» массива?
  • Поиск суммы элементов в массиве Swift
  • Измененный массив в области файлов
  • Как объявить элементы массива volatile в Java?
  • Как изменить массив int в Java?
  • Давайте будем гением компьютера.