Можно ли привести (скастить) двумерный массив к T**?

Рейтинг: 1Ответов: 4Опубликовано: 11.05.2023

Я пробовал данный способ:

double arr[5][5];
double **ptr = (double **)arr;

Все это дело компилируется, но обращение ptr[][] к массиву используя указатель приводит к: SEGFAULT

Собственно, вопрос, можно ли осуществить взаимодейстие с двумерным массивом через ptr**?

Ответы

▲ 2

Ну... можно так:

double arr[5][5];
double *ptr = (double *)arr;

А обращение arr[i][j] при этом будет выглядеть как

*(ptr + 5*i+j)

https://ideone.com/VIKiTT

▲ 1

В чём ошибка?

double arr[5][5];
double** ptr = (double**)arr;

Вот здесь вы скастили double(*)[5] к double**. Дальше, при первом разыменовании arr[row] вы получаете мусорный адрес, а при втором arr[row][col] - segfault.

Конструкция array[idx] является синтаксическим сахаром для *(array+idx). Таким образом, array[row][col] - это *(*(array+row)+col).

Массивы и указатели

Массив может быть приведён только к указателю на первый элемент (array to pointer decay). Двумерные массивы тут исключением не являются:

constexpr int rows = 5;
constexpr int cols = 7;

double array[rows][cols];

double (*ptr1)[cols] = array; // double(*)[7] - указатель на массив double[7]

double* ptr2 = *array; // уазатель на первый элемент первого подмассива
// здесь происходит двойной 'array to pointer decay' через разыменование

for (int row = 0; row < rows; ++row)
    for (int col = 0; col < cols; ++col)
        ptr2[row*cols+col] = 0; // any expression

C++23: operator[]

А ещё в C++23 появился operator[](Ts...), который может принимать аргументы разных типов по принципу: object["string"s,37,3.14159]. Так что вы можете создать свой класс для удобства: array[row,col].

▲ 0

Нет. В статической матрице присутствуют элементы только типа double. А в массиве указателей первые элементы только типа указатель double *.
И приведение к неправильному типу приводит только к неопределённому поведению.

▲ 0

Ошибка сегмента SEGFAULT, в твоём случае происходит от того что С чито физический не может понять от какого места начинать следующий сегмент.

Фактический он знает где находится элемент [0][0], а вот где находится [1][0] после того как ты привел значение в указатель?

double* - это уже не массив, это некий адрес в памяти, в котором возможно что-то хранится (а возможно и нет), и каков размер сегмента памяти, и каков обьем памяти может предсказать только ванга или программист ручками.

Сделай указатель на [0][0] просто сказав что double* а второй ряд массива доставай простой математикой - 7й элемент многомерки это будет твой 0й элемент первого [1][0] ряда.

И - да естественно что double* можно привести обратно в double X[5][5] используя обычное статическое преобразование.

Это как раз очень сильная сторона С и Pascal, что все что угодно может стать памятью и память может обратно стать объектом.