Динамическое выделение 2d-массива и его инициализация (ошибка сегментации)

Я изучаю C, и я попытался выделить память для 2D-массива (размеры массива я получаю от пользователя), но я получаю ошибку сегментации после того, как пытаюсь его инициализировать. Мой код таков:

#include <stdio.h>
#include <stdlib.h>

int main()
{
   printf("give the dimensions!\n");
   int row,col,i,j; 
   int **myArray;

   printf("\nrows = ");
   scanf("%d", &row);
   printf("columns = ");
   scanf("%d", &col);
   myArray = malloc(row*sizeof(*myArray) + col*sizeof(**myArray));

   printf("Init the array: \n");
   for (i = 0; i < row; i++)
   {
       for (j = 0; j <col ; j++)
       {
           scanf("%d", &myArray[i][j]);
       }
   }

   return 0;
}

Если я изменяю массив как myArray[2][2] и опускаю оператор malloc, он работает нормально.


person yaylitzis    schedule 19.12.2013    source источник
comment
добавьте пространство к scanf(" %d", &myArray[i][j]);, как только вы действительно приступите к размещению 2D-массива   -  person Elias Van Ootegem    schedule 19.12.2013


Ответы (3)


C не может узнать, как должна работать ваша индексация: нет информации, связывающей количество столбцов (col) с myArray. Когда вы выполняете myArray[i][j] с myArray, объявленным как int * *, C сначала оценит myArray[i], т.е. прочитает i:th значение myArray, как если бы это был целочисленный указатель, чего в вашем случае нет. Затем он проиндексирует j из этого недопустимого значения, что, вероятно, приведет к ошибке сегментации (по крайней мере, к неопределенному поведению).

Делая это вручную, у вас есть два варианта:

  • Сделайте его «зубчатым», где каждая строка имеет свой собственный указатель на элементы этой строки. Это то, что @bgamlath предлагает в своем ответе.
  • Сделайте индексацию самостоятельно, заменив myArray[i][i] на myArray[i * cols + j].

Последний использует меньше памяти и (путь) меньше памяти, что приятно. Конечно, индексация может быть немного неудобной.

person unwind    schedule 19.12.2013

Попробуйте сделать это так.

  table = malloc(row*sizeof(int *));
  for(i = 0; i<row; i++)
    table[i] = malloc(col * sizeof(int));
person Buddhima Gamlath    schedule 19.12.2013
comment
да, я только что увидел здесь еще один вопрос, похожий на мой stackoverflow.com/questions/19059151/ спасибо!!! - person yaylitzis; 19.12.2013
comment
Это не двумерный массив, это таблица поиска на основе указателя. 2D-массивы размещаются в соседней памяти. Вот как вы выделить 2D-массив. - person Lundin; 19.12.2013

Вы можете выделить динамические массивы, как это. malloc не требуется.

{ 
  printf("rows = ");
  scanf("%d", &rows);
  printf("columns = ");
  scanf("%d", &cols);

  int my_array[rows][cols];
}

Чтобы обнулить новый массив:

  memset(my_array, 0, rows*cols*sizeof(int));
person Darren Stone    schedule 19.12.2013
comment
только с C99 и при условии, что ввод не слишком велик и вызывает переполнение стека - person Elias Van Ootegem; 19.12.2013
comment
Абсолютно. Любой, кто не работает с C99 или выше, должен придерживаться malloc и free. Поскольку @Nat95 говорит нам, что он новичок, я направляю его к VLA по двум причинам: 1) удобство нотации, особенно с многомерными массивами, которые он ищет, и 2) свобода от бесконечных ошибок новичка C, связанных с malloc и free. - person Darren Stone; 19.12.2013