Выделение массива целых чисел 2d в C

#c #memory

#c #память

Вопрос:

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

Теперь я пробовал это разными способами (смещение, арифметика указателей), но не нашел решения проблемы.

Я либо получаю мусорные значения, либо программа выходит из строя (ошибка seg отсутствует, сбой кода ошибки).

Я также ищу подходящую версию для выделения памяти, я видел несколько версий в stackoverflow, ту, которую я бы предпочел использовать, — это выделение пространства указателей и последующего целочисленного пространства (то, которое я пытаюсь использовать в примере ниже).

    // Convert a matrix to it's transposed version. Returns a two dimensional array (pointer)
int **getTransposedMatrix(int *matrix, int dimension_h, int dimension_w){
    int **transposedMatrix = (int **) malloc(dimension_w * sizeof(int*));

    for(int row=0; row<dimension_w; row  ){
        transposedMatrix[row] = (int*) malloc(dimension_w * sizeof(int));
    }

    for(int row=0; row<dimension_h; row  ){
        for(int column=0; column<dimension_w; column  ){
            transposedMatrix[column][row] = *(matrix   row * dimension_w   column);
         printf("%d ", transposedMatrix   (row * dimension_w   column));
        }
        printf("n");
    }
    return **transposedMatrix;
}
 

Я ценю любую помощь 🙂

Комментарии:

1. При распределении вы используете dimension_w для распределения оба измерения. Одно измерение должно быть dimension_h

2. Это потому, что он должен возвращать транспонированную матрицу, хотя и пробовал это.

3.Понимание int** не имеет абсолютно никакого отношения к какому-либо массиву или 2D-массиву. Это просто указатель на указатель int . (это один указатель, который указывает на блок указателей) Для каждого из указателей в блоке вы можете назначить адрес блока, содержащего несколько int значений, для имитации 2D-массива.

4. Если транспонировано, должно ли это быть transposedMatrix[row] = (int*) malloc(dimension_h * sizeof(int)); , например w , строки по h столбцам?

5. Оператор return неверен return **transposedMatrix; , он возвращает элемент в верхнем левом углу.

Ответ №1:

Я бы не стал беспокоиться о «2D-массиве», таком как тот, который вы настраиваете, где вы выделяете строки отдельно. Ниже приведена моя версия, которая использует один массив и соответственно вычисляет в нем смещения.

 int *getTransposedMatrix(int *matrix, int dimension_w, int dimension_h)
{
    int *transposed = malloc(dimension_w * dimension_h * sizeof(int));
    for (int row = 0; row < dimension_h; row  ) {
        for (int col = 0; col < dimension_w; col  ) {
            transposed[col * dimension_h   row] = matrix[row * dimension_w   col];
        }
    }
    return transposed;
}
 

ideone с некоторыми тестовыми примерами

Комментарии:

1. Спасибо за вашу помощь 🙂 Я бы предпочел иметь решение для отдельного выделения, я знаю, как сделать сольный указатель 🙂

2. В этом случае ваш исходный код верен, но просто измените оператор return на: return transposedMatrix; . Однако я должен отметить, что, если вы не работаете с очень большими матрицами и вам не нужно много эффективно перемещать строки, этот способ выделения пространства не имеет смысла. РЕДАКТИРОВАТЬ: И вам не нужно приводить malloc() . EDIT2: и ваш оператор печати должен быть просто: printf("%d", transposedMatrix[column][row]);

3. Большое вам спасибо за вашу помощь @vmt 🙂 Я обычно выделяю свои выделения памяти, я думаю, что это хорошая практика, также синтаксис [column] [row] работает только при работе с таким распределением, верно? Я не уверен, но я обязательно изучу арифметику указателей с использованием скобок еще раз, еще раз спасибо! 🙂

4. когда вы приводите его к an int** , откладывая один раз, вы получаете int* и дважды, int . Кроме того, приведение ваших распределений в C совершенно не нужно, поскольку приведение from void* является неявным. Кроме того, это может скрыть тот факт, что вы, возможно, не включили stdlib.h из-за неявных объявлений. Неявные объявления больше не имеют возвращаемого типа int , который находится в >= c99 , но на практике компилятор выдает предупреждение. Даже за исключением всего этого, в целом это считается плохой практикой.