Можно ли привести (скастить) двумерный массив к T**?
Я пробовал данный способ:
double arr[5][5];
double **ptr = (double **)arr;
Все это дело компилируется, но обращение ptr[][] к массиву используя указатель приводит к: SEGFAULT
Собственно, вопрос, можно ли осуществить взаимодейстие с двумерным массивом через ptr**?
Ответы (4 шт):
Ну... можно так:
double arr[5][5];
double *ptr = (double *)arr;
А обращение arr[i][j] при этом будет выглядеть как
*(ptr + 5*i+j)
В чём ошибка?
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].
Нет. В статической матрице присутствуют элементы только типа double. А в массиве указателей первые элементы только типа указатель double *.
И приведение к неправильному типу приводит только к неопределённому поведению.
Ошибка сегмента SEGFAULT, в твоём случае происходит от того что С чито физический не может понять от какого места начинать следующий сегмент.
Фактический он знает где находится элемент [0][0], а вот где находится [1][0] после того как ты привел значение в указатель?
double* - это уже не массив, это некий адрес в памяти, в котором возможно что-то хранится (а возможно и нет), и каков размер сегмента памяти, и каков обьем памяти может предсказать только ванга или программист ручками.
Сделай указатель на [0][0] просто сказав что double* а второй ряд массива доставай простой математикой - 7й элемент многомерки это будет твой 0й элемент первого [1][0] ряда.
И - да естественно что double* можно привести обратно в double X[5][5] используя обычное статическое преобразование.
Это как раз очень сильная сторона С и Pascal, что все что угодно может стать памятью и память может обратно стать объектом.