C, Динамическое размещение матрицы: почему это не разрешено?

Итак, у меня есть следующий пример в некоторых конспектах

void f(int **p){}
void g(int *p[]){}
void h(int p[2][3]){}

int main(){
   int **a;
   allocate_mem(a); // allocate memory for a
   f(a); // OK!
   g(a); // OK!
   // h(a); // NOT OK
   int b[2][3];
   // f(b); // NOT OK
   // g(b); // NOT OK
   h(b); // OK!
   return 0;
}

(без каких-либо дополнительных объяснений / комментариев). Я изо всех сил пытаюсь понять, почему именно f(b) и g(b) были бы незаконными. Обе эти функции предназначены для приема двумерных массивов, и мы вызываем их с одним. Как это не работает? Я предполагаю, что разница заключается в распределении памяти, но как это повлияет на то, как функция принимает это как ввод?

1 ответ

Решение

Вы объединяете указатели с массивами и указатели на указатели с двумерными массивами.

Это понятная ошибка из-за "затухания массива в указателе" в C (и C++). Иногда вы можете обратиться к массиву и получить указатель на его первый элемент; иногда это фактический массив - зависит от контекста. А с двумерными массивами это становится еще более странным, поскольку двумерные массивы могут использоваться в меньшем количестве мест вместо указателя на указатель на элемент (но все же могут использоваться в некоторых местах, подобных этому).

Пожалуйста, уделите несколько минут чтению о том, как указатели и массивы связаны и различаются, в Разделе 6 FAQ по языку C. Ваш конкретный вопрос также появляется там:

В 6.18: "Мой компилятор пожаловался, когда я передал двумерный массив функции, ожидающей указатель на указатель".

Другие вопросы по тегам