Выделение памяти под матрицу на C, почему я не могу потом получить доступ к матрице?

Я использую malloc для выделения памяти для матрицы, но впоследствии любой доступ к матрице для установки элемента, например, приводит к ошибке сегментации.

Вот что я делаю прямо сейчас:

int **matrix = malloc(rows_number * columns_number * sizeof(int));

if (matrix) matrix[0][0] = 1;

Почему я не могу получить доступ к матрице после ее создания? Вызов malloc выполнен успешно, поэтому у меня достаточно непрерывной памяти для всей матрицы.


person Kao Dome    schedule 19.12.2012    source источник
comment
malloc — это наименее понятая и наиболее обсуждаемая часть языка C — пожалуйста, поищите здесь и в других местах множество ответов на этот и любой другой мыслимый вопрос по этой теме. честно говоря, я не могу поверить, что есть вопрос о malloc, который не был задан - и на него не ответили :)   -  person KevinDTimm    schedule 19.12.2012
comment
возможный дубликат матрицы распределения в C   -  person KevinDTimm    schedule 19.12.2012
comment
См. главный ответ на этот вопрос: ‹stackoverflow.com/questions/917783/  -  person BimmerM3    schedule 19.12.2012
comment
@ BimmerM3, этот главный ответ просто неверен. Это не двумерный массив, а указатель на эмуляцию указателя двумерного массива. C имеет встроенную поддержку 2D-массива, почему бы не использовать ее?   -  person Jens Gustedt    schedule 20.12.2012


Ответы (4)


Проблема здесь в том, что вы выделили только память, но объявили свой объект как набор указателей на указатели. Для двойного нижнего индекса требуется вектор-указатель, указывающий на каждую строку или тип, сообщающий компилятору, сколько имеется столбцов.

Итак, некоторые варианты:

  • выполнить расчет нижнего индекса с помощью кода, возможно, с помощью макроса
  • сделать два mallocs() и инициализировать вектор указателя строки
  • malloc объект определенного типа, чтобы компилятор мог его увидеть

Например...

int (*matrix)[ROWS][COLS] = malloc(ROWS * COLS * sizeof(int));
...
(*matrix)[i][j]

Следующее объявление также будет работать:

int (*matrix)[][COLS] = malloc(ROWS * COLS * sizeof(int));
person DigitalRoss    schedule 19.12.2012
comment
Извините за поздний ответ, я вижу, что я делал неправильно. Я отмечаю этот ответ как принятый, потому что он кажется наиболее полным. Спасибо. - person Kao Dome; 31.12.2012

int **matrix объявляет matrix указателем на указатель на int. Вам нужен указатель на массив int. Это будет int (*matrix)[columns_number]. Вы можете красиво распределить его с помощью:

int (*matrix)[columns_number] = malloc(rows_number * sizeof *matrix);
person Eric Postpischil    schedule 19.12.2012
comment
Я вижу, спасибо за ответ, я отметил другой как принятый, потому что он показался более полным, но мне нравится этот способ сделать это, потому что доступ к матрице более интуитивно понятен. - person Kao Dome; 31.12.2012

Вы выделили память для динамического массива целых указателей, а не для элементов int. Вы можете попробовать что-то вроде этого:

int *matrix_storage = malloc(rows_number * columns_number * sizeof(int));
int **matrix = malloc(rows_number * sizeof(int*));
for( int i = 0; i < rows_number; ++i )
    matrix[i] = &matrix_storage[ i * columns_number ];
person K-ballo    schedule 19.12.2012

Malloc возвращает пустой указатель, поэтому вы не создали двумерный массив. Попробуйте что-то вроде:

int **matrix;
matrix = malloc(rows_number * sizeof(int*));
for (int i=0; i<rows_number; i++)
    matrix[i] = (int*)malloc(columns_number * sizeof(int));
person Foggzie    schedule 19.12.2012