m[line][column] = 12
синтаксис в порядке (если line
и column
находятся в диапазоне).
Однако Вы не написали код, который Вы используете для выделения его, таким образом, трудно добраться, неправильно ли это или правильно. Это должно быть что-то вроде
m = (int**)malloc(nlines * sizeof(int*));
for(i = 0; i < nlines; i++)
m[i] = (int*)malloc(ncolumns * sizeof(int));
Некоторые заметки на полях:
Ваш синтаксис m [строка] [столбец] правилен. Но для использования 2D массива в C, необходимо выделить память для него. Например, этот код будет выделенная память для таблицы данной строки и столбца.
int** AllocateArray(int line, int column) {
int** pArray = (int**)malloc(line*sizeof(int*));
for ( int i = 0; i < line; i++ ) {
pArray[i] = (int*)malloc(column*sizeof(int));
}
return pArray;
}
Примечание, я не учел проверки на ошибки на malloc для краткости. Действительное решение должно включать их.
Это не 2-й массив - это - массив массивов - таким образом требуется несколько выделений.
Вот измененная версия решение quinmar, которое только выделяет единственный блок памяти и может использоваться с универсальными значениями любезностью void *
:
#include <stdlib.h>
#include <string.h>
#include <assert.h>
void ** array2d(size_t rows, size_t cols, size_t value_size)
{
size_t index_size = sizeof(void *) * rows;
size_t store_size = value_size * rows * cols;
char * a = malloc(index_size + store_size);
if(!a) return NULL;
memset(a + index_size, 0, store_size);
for(size_t i = 0; i < rows; ++i)
((void **)a)[i] = a + index_size + i * cols * value_size;
return (void **)a;
}
int printf(const char *, ...);
int main()
{
int ** a = (int **)array2d(5, 5, sizeof(int));
assert(a);
a[4][3] = 42;
printf("%i\n", a[4][3]);
free(a);
return 0;
}
я не уверен, действительно ли безопасно бросить void **
к int **
(я думаю, что стандарт позволяет, чтобы преобразования произошли при преобразовании в void *
?), но это работает в gcc. Чтобы быть на безопасной стороне, необходимо заменить каждое происшествие void *
с int *
...
следующая реализация макросов безопасная с точки зрения типов версия предыдущего алгоритма:
#define alloc_array2d(TYPE, ROWS, COLS) \
calloc(sizeof(TYPE *) * ROWS + sizeof(TYPE) * ROWS * COLS, 1)
#define init_array2d(ARRAY, TYPE, ROWS, COLS) \
do { for(int i = 0; i < ROWS; ++i) \
ARRAY[i] = (TYPE *)(((char *)ARRAY) + sizeof(TYPE *) * ROWS + \
i * COLS * sizeof(TYPE)); } while(0)
Используют их как это:
int ** a = alloc_array2d(int, 5, 5);
init_array2d(a, int, 5, 5);
a[4][3] = 42;
Хотя я соглашаюсь с другими ответами, в большинстве случаев лучше выделить целый массив сразу, потому что malloc является довольно медленным.
int **
array_new(size_t rows, size_t cols)
{
int **array2d, **end, **cur;
int *array;
cur = array2d = malloc(rows * sizeof(int *));
if (!array2d)
return NULL;
array = malloc(rows * cols * sizeof(int));
if (!array)
{
free(array2d);
return NULL;
}
end = array2d + rows;
while (cur != end)
{
*cur = array;
array += cols;
cur++;
}
return array2d;
}
Для освобождения массива просто сделайте: free(*array); free(array);
Примечание: это решение только работает, если Вы не хотите изменять порядок строк, потому что Вы могли затем потерять адрес первого элемента, который необходимо освободить массив позже.
Humm. Как насчет старомодного обмана как опция?
#define ROWS 5
#define COLS 13
#define X(R, C) *(p + ((R) * ROWS) + (C))
int main(void)
{
int *p = (int *) malloc (ROWS * COLS * sizeof(int));
if (p != NULL)
{
size_t r;
size_t c;
for (r = 0; r < ROWS; r++)
{
for (c = 0; c < COLS; c++)
{
X(r,c) = r * c; /* put some silly value in that position */
}
}
/* Then show the contents of the array */
for (r = 0; r < ROWS; r++)
{
printf("%d ", r); /* Show the row number */
for (c = 0; c < COLS; c++)
{
printf("%d", X(r,c));
}
printf("\n");
}
free(p);
}
else
{
/* issue some silly error message */
}
return 0;
}
Используя malloc(3)
для выделяют первый массив, и помещающий там указатели, созданные malloc(3)
, должен работать с array[r][c]
, потому что это должно быть эквивалентно *(*(array + r) + c)
, это находится в стандарте C.