double**
- указатель на указатель. Конечно, (внешний) указатель также может указывать на некоторый массив:
double* array[7];
double** pointer = array;
Теперь каждый из указателей в array
может указывать и на другие массивы:
double valueArray[12]
double* pointerArray[10];
double** pointer = array;
pointer[0] = valueArray; // equivalent to pointerArray[0] = ...
Двумерные массивы не являются массивами указателей, хотя они являются массивами массивов, и указатель на первый элемент имеет другой тип:
double array[10][12];
double(*pointer)[12] = array;
Попытка охватить матрицы произвольного размера вызывает некоторые проблемы:
struct Matrix
{
size_t n;
double(*data)[n]; // you cannot exchange arbitrary pointers,
// you need a compile time constant!
};
Имейте в виду, что это отличается от VLA в параметрах функций, где вы могли бы иметь
void f(size_t n, int(*data)[n]);
Тогда это выглядит так, как будто у вас уже есть большие проблемы с битом кода Вы представили:
void someFunction(Matrix* m)
{
double array[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
m->data = array; // assuming you meant m instead of A
// and you did adjust the pointer type already appropriately
}
array
имеет локальную продолжительность хранения и будет уничтожена, как только вы вернетесь из функции, что приведет к зависанию указателя в m
и неопределенному поведению, если вы разыграете указатель после возврата из функции.
Так что вам нужно вместо этого malloc
массив достаточного размера. Но не забудьте освободить его и тогда!
Так что, если вы не хотите go указатель на путь указателя:
double** array = malloc(sizeof(*array) * n);
array[0] = malloc(sizeof(**array) * n);
// ...
который допускает синтаксис m->data[x][y]
, тогда вам следует придерживаться подхода одномерного массива:
struct Matrix
{
size_t n;
double* data;
};
и, возможно, некоторой функции доступа:
double get(struct Matrix* m, size_t row, size_t column)
{
return m->data[row * m->n + column];
}
, которая получит вокруг косвенности двойного указателя и, следовательно, быстрее (на самом деле, это точно такое же вычисление, которое происходит под капотами с истинным двумерным массивом, т.е. не указатель на вариант указателя).