Как транспонировать матрицу указателей

У меня есть матрица макета

const int boatRect[MAX_BITMAP_SIZE][MAX_BITMAP_SIZE] = { // 5
        {0, 0, 1, 0, 0},
        {0, 0, 1, 0, 0},
        {0, 0, 1, 0, 0},
        {0, 0, 1, 0, 0},
        {0, 0, 1, 0, 0}
};

и структуру с указателем на нее (матрицу):

typedef struct bitmap {
    Shape shape;
    const int (*matrix)[MAX_BITMAP_SIZE];
    int orientation;
    int size;
} Bitmap;

Затем я хочу транспонировать (часть процесса вращения) матрицу в структуре:

void transpose(const int (*shape)[MAX_BITMAP_SIZE]) {
    const int *temp;
    for(int i = 0; i < MAX_BITMAP_SIZE; i++) {
        for(int j = 0; j < i; j++) {
            temp = (const int *) shape[i][j]; //Cast to 'const int *' from smaller integer type 'int'
            shape[i][j] = shape[j][i];        //Read-only variable is not assignable
            shape[j][i] = temp;               //Read-only variable is not assignable
        }
    }
}

но я получаю эти ошибки, я не уверен, что я делаю неправильно!

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

Итак, как мне в моей структуре Bitmap создать матрицу указателей, указывающих на матрицу const int, а затем повернуть эту матрицу указателей (а не матрицу int)?


person obvionaoe    schedule 21.04.2020    source источник
comment
Вам нужно изменить сигнатуру функции на void transpose(int (*shape)[MAX_BITMAP_SIZE]) Предупреждение о приведении останется, но вы можете избавиться от этого, изменив const int *temp; на const int temp; и удалив приведение (поскольку вы назначаете int для int).   -  person Louis Cloete    schedule 21.04.2020


Ответы (1)


Ваша матрица не является «матрицей указателей», которая была бы матрицей, элементы которой являются указателями. Это матрица целых чисел. Вы определяете его как массив массивов int.

const int boatRect[MAX_BITMAP_SIZE][MAX_BITMAP_SIZE] = { ... };

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

const int (*matrix)[MAX_BITMAP_SIZE];

Разыменование дважды даст вам int, а именно целочисленное значение в данной строке и столбце. Следовательно, ваша переменная temp для обмена должна быть int:

int temp = shape[i][j];

Нет необходимости в литье! (Предупреждение означает, что ints «уже», чем указатель в вашей системе, и что вы потеряете информацию в задании.)

С этим изменением вторая ошибка по-прежнему будет сохраняться: вы создали матрицу const: элементы const T* не могут быть изменены. Если вы хотите изменить матрицу на месте, не делайте ее const. (Вы по-прежнему можете сделать это локально const в функциях, которые обращаются к нему, но не изменяют его.)

person M Oehm    schedule 21.04.2020
comment
Я знаю, что исходная матрица не является матрицей указателей, но я хочу иметь матрицу указателей, которая указывает на нее, а затем повернуть эту матрицу указателей. - person obvionaoe; 21.04.2020
comment
Итак, вы хотите иметь матрицу, элементы которой являются указателями на целые элементы исходной матрицы? А если вы инвертируете матрицу, вы просто меняете местами указатели? На мой взгляд, это не имеет смысла. У вас есть указатель на матрицу, так что ваша структура просто хранит указатель, не копируя всю матрицу. Если вы измените матрицу с помощью этого указателя, вы измените исходную матрицу, потому что они одинаковы. - person M Oehm; 21.04.2020
comment
тогда как лучше всего иметь в памяти только одну матрицу? потому что это моя цель, иначе я бы не возился с указателями, я бы просто скопировал его - person obvionaoe; 21.04.2020
comment
Это то, что вы сделали, за исключением того, что у вас, кажется, неправильное представление о том, какой частью является указатель: указатель — это внешняя часть; это не влияет на внутренние части. Возьмите простой массив: int a = [1, 2, 3]. Теперь определите указатель на него: int *p = a. И a[0], и p[0] обращаются к первому элементу a, и присвоение нового значения p[0] также изменит элемент a[0] базового массива. Это то, чего ты хочешь, верно? (продолжение) - person M Oehm; 21.04.2020
comment
Обратите внимание, что здесь элементы как a, так и p являются ints. p сам по себе является указателем, но он указывает на целые числа. Теперь вы используете этот метод для двумерного массива int M[5][5]. Элементы M представляют собой массивы из пяти целых чисел. Указатель на этот массив представляет собой int (*P)[5]. (Сначала к этому синтаксису нужно привыкнуть.) P указывает на массив из пяти целых чисел, а M[0] и P[0] обращаются к первой строке вашей матрицы. Чтобы получить целое число в определенном столбце этой строки, вы должны указать второй индекс: M[0][i] и P[0][j] — одно и то же целое число. - person M Oehm; 21.04.2020
comment
Я просто хочу перейти туда, куда указывает указатель, на самом деле я не хочу менять значения! Если бы у меня была матрица 2 * 2 с { {0,1}, {0,1} }, я бы хотел, чтобы каждая структура имела матрицу указателей { {ptr1, ptr2}, {ptr3, ptr4} }, а в моей функции поворота я хочу, чтобы эта матрица указателей была повернута { {ptr2, ptr4}, {ptr1, ptr3} }, но сохранила исходную матрицу как { {0,1}, {0,1} }! можно так сделать или это совсем тупо? Я просто пытаюсь иметь как можно меньше ресурсов в памяти:/ - person obvionaoe; 21.04.2020
comment
Возможно, здесь может быть полезен typedef: typedef int Matrix5x5[5][5]; Определите матрицу с помощью Matrix5x5 m = {{...}};. Теперь член вашей структуры, указатель на эту матрицу, равен Matrix5x5 *p;, как и для любого другого типа. (Но создание определений типов для массивов фиксированных размеров скрывает природу типа, поэтому я обычно этого не делаю.) - person M Oehm; 21.04.2020
comment
Но таким образом у меня будет указатель на матрицу, я хочу матрицу указателей - person obvionaoe; 21.04.2020
comment
Давайте продолжим это обсуждение в чате. - person obvionaoe; 21.04.2020
comment
Хорошо, мы говорили здесь на перекрестке. На самом деле вы действительно хотели иметь матрицу указателей. Это не глупо, но я не вижу здесь реальной выгоды. Ваш базовый тип данных, целые числа, мал, обычно меньше указателя. Создание новой матрицы так же дешево с точки зрения памяти, как и создание матрицы указателей. Использование массива указателей по-прежнему полезно: представьте, что у вас есть одномерный массив больших объектов, каждый из которых имеет килобайт. Вы хотите отобразить их в определенном порядке. Вместо их сортировки создайте массив облегченных указателей и отсортируйте его косвенно. - person M Oehm; 21.04.2020
comment
В любом случае, если вы хотите иметь матрицу указателей, определите int *pm[5][5]. Вы больше не можете назначать матрицу одной инструкцией, вы должны явно инициализировать каждый элемент с помощью pm[j][i] = &m[j][i]. - person M Oehm; 21.04.2020