Вопрос по – Выделение памяти для 2d матрицы с использованием 1 вызова malloc

2
We can allocate memory for 2d matrix using 1 malloc call as
int (*a)[5];
int i,j;

a = malloc (sizeof (int *) * 5); // выделяем 5 указателей                             и каждый указатель указывает на массив 5 дюймов

Как мы можем освободить эту память успешно распределенной? Использование free (a) дает ошибку во время выполнения

С помощью для (я = 0; я & л; 5; я ++) бесплатно (а [I]);

бесплатно (а);

Это также дает ошибку во время выполнения

a=malloc(sizeof(int*) * 5); фактически выделяет память для 5-элементного массива указателей int, в то время какint (*a)[5] означает указатель на массив из 5 mrpyo

Ваш Ответ

1   ответ
10

Изменить: ВЕСЬ ИСТОРИЯ.

Ранее я игнорировалTHREE другие способы размещения 2d массивов.

Dynamic 2d array method 1:

Этот работает, если вы знаете количество столбцов во время компиляции.

#define CCOLS 200

int (*m)[CCOLS] = malloc(cRows * sizeof(*m));
m[iRow][iCol] = n; // sets the item at iRow*CCOLS + iCol

...

free(m);

Это работает, потому что m объявлен как указатель на массив целых чисел CCOLS. Компилятор знает его размер и делает математику за вас. m [iRow] = массив целых чисел CCOLS.

Вы можете передать это только функциям с этой подписью:

foo(int (*m)[CCOLS]) { ... }

и, возможно, эта подпись, в зависимости от вашего компилятора и используемых вами ключей:

foo(int m[][CCOLS]) { ... }

не эта подпись

foo(int **m) { ... }

Так как макеты памяти и размеры разные.

int m [] [CCOLS] выглядит так:

+---------+---------+---------+---------+     
| m[0][0] | m[0][1] | m[0][2] | m[0][3] |     
+---------+---------+---------+---------+     
| m[1][0] | m[1][1] | m[1][2] | m[1][3] |     
+---------+---------+---------+---------+     
| m[2][0] | m[2][1] | m[2][2] | m[2][3] |     
+---------+---------+---------+---------+     
| m[3][0] | m[3][1] | m[3][2] | m[3][3] |     
+---------+---------+---------+---------+     

int ** m выглядит так:

+----+        +----+----+----+----+----+      
|m[0]|  --->  |    |    |    |    |    |      
+----+        +----+----+----+----+----+      
|m[1]|  --->  |    |    |    |    |    |      
+----+        +----+----+----+----+----+      
|m[2]|  --->  |    |    |    |    |    |      
+----+        +----+----+----+----+----+      
|m[3]|  --->  |    |    |    |    |    |      
+----+        +----+----+----+----+----+      

Dynamic 2d array method 2 (C99 which is not supported by all compilers):

Это то же самое, что и предыдущий, но вам не нужно знать размеры во время компиляции.

int cCols, cRows, iCol, iRow;
... set cRows, cCols somehow, they could be passed in as parameters also ...
int (*m)[cCols] = malloc(cRows * sizeof(*m));
m[iRow][iCol] = n; // sets the item at iRow*cCols + iCol

...

free(m);

Вы можете передать это только функциям с этой подписью:

foo(int cCols, m[][cCols])  {}

или этот

foo(int cRows, int cCols, m[cRows][cCols])  {}

Если вы используете GCC, здесь большеИнформация.

Dynamic 2d array method 3 using the STACK! (C99 which is not supported by all compilers):

Это позволяет полностью избежать malloc, если вы в порядке с вашим 2d-массивом в стеке.

int cRows, cCols;
... set cRows, cCols somehow ...
int m[cRows][cCols];
m[iRow][iCol] = n; 

Я предполагаю, что вы могли бы объявить глобальную переменную таким же образом.

Вы передаете это функциям так же, как метод 2.

Dynamic 2d array method 4:

Это метод массива указателей, который используют многие люди.

Вы используете один malloc для выделения, чтобы быть эффективным. И, конечно, вы используете только один бесплатный. Только если у вас есть ОГРОМНЫЕ массивы, в которых возникает и возникает непрерывная память, вы захотите распределить каждую строку по отдельности.

int cCols = 10, cRows = 100, iRow;

// allocate:
// cCols*cRows*sizeof(int) = space for the data
// cRows*sizeof(int*) = space for the row ptrs
int **m = malloc(cCols*cRows*sizeof(int) + cRows*sizeof(int*));

// Now wire up the row pointers.  They take the first cRows*sizeof(int*) 
// part of the mem becasue that is what m[row] expects.
// we want each row pointer to have its own cCols sized array of ints.
// We will use the space after the row pointers for this.
// One way to calc where the space after the row pointers lies is to
// take the address of the nth + 1 element: &m[cRows].
// To get a row ptr, cast &m[cRows] as an int*, and add iRow*cCols to that.
for (iRow = 0; iRow < cRows; ++iRow)
    m[iRow] = (int*)&m[cRows] + iRow*cCols; 

// or 
for (p=(int*)&m[cRows] ; iRow = 0; iRow < cRows; ++iRow, p+=cCols)
    m[iRow] = p; 


// use it:
...
m[iRow][iCol] = 10;
...

// free it
free(m);
Спасибо за удивительно четкое решение.
Большое спасибо за такое хорошее решение Luv
ИНТ*m = malloc(cxсуsizeof(int) + cySizeOf (INT *)); В этой строке второй член должен быть cxsizeof(int), если вы делаете указатели строк. Следовательно, указатели строк будут 10 каждый из 100 элементов. Поправьте меня если я не прав Luv
@Luv: Это будет не первый раз, когда у меня будет ошибка ... Я думаю, что это правильно, так как cy - это число строк. Таким образом, вам нужны указатели строки Cy, которые потребуют Cysizeof(intбайт. Я прокомментирую код, чтобы сделать его понятным "y" является счетчиком строк, а cy является счетчиком строк.

Похожие вопросы