Исчезнувший многомерный массив, возвращаемый из функции - PullRequest
0 голосов
/ 27 марта 2010

относится к (gcc) Multi-Dim Array или Double Pointer для безошибочной компиляции , есть ли способ вернуть так называемый «указатель на затухающий массив» из функции? в итоге (предположим, 2 dim array), возвращающий формат int (*a)[5] вместо int** format?

Насколько я вижу, когда возвращенный указатель int** отправляется другой функции, ожидающей параметра (int*)[], он работает неправильно.

Ответы [ 2 ]

4 голосов
/ 27 марта 2010

Да, но синтаксис выглядит не очень хорошо

int(*f())[5] {
  static int a[1][5] = { { 1, 2, 3, 4, 5 } };
  return a;
}

По сути, это просто ваш a, замененный f() (функция). Использование typedef становится более читабельным

typedef int inner_array[5];

inner_array *f() {
  // like before ...
}

Обратите внимание, что для обозначения абсолютного типа без имени необходимо написать int(*)[5]. То есть вы просто стираете имя. (int*)[5] недопустимый синтаксис.

Вы правы - вы не можете вернуть int**, потому что это означает, что у вас есть указатель на указатель. Доступ с помощью f()[A][B] будет считывать с адреса, который возвращает возвращенный указатель, а затем снова читать с адреса, указанного этим указателем по очереди. Но на самом деле указатель массива, который вы возвращаете, указывает только на один блок памяти, поэтому, если вы сделаете две косвенные ссылки, вы попытаетесь интерпретировать данные как указатели.

Наоборот, если вы вернете int(*)[5] и введете f()[A][B], вы не будете читать значения с адреса, возвращаемого указателем. Вместо этого вы просто добавляете к адресу смещение A и настраиваете тип от int(*)[5] до int[5], чтобы получить массив, который ссылается на память по настроенному адресу. Затем следующий индекс будет снова скорректирован на B, и, поскольку он работает с int*, то (после того, как массив распался), больше не по указателю массива, он будет затем читать содержимое, сохраненное по скорректированному адресу, чтобы в итоге получить int. Это важное отличие от указателей не-массивов и указателей массивов.

Вы можете поэкспериментировать с этим, если хотите. Рассмотрим эти два фрагмента. Один из них, вероятно, потерпит крах, но другой, вероятно, не будет (но оба приведут к неопределенному поведению, поэтому этого не следует делать в реальных программах)

int *pi = 0; 
int(*pa)[5] = 0;

int i = *pi; // read int stored at null-pointer address!
int *a = *pa; // does not read any data from address, just adjusts the type!
0 голосов
/ 29 марта 2010
struct thing {
   int A[10][10];
};

typedef struct thing thing_t;

thing_t f1(void) {
    thing_t t;
    ...
    return t;
}
thing_t * f1(void) {
   thing_t * tp;
   ...
   return tp;
}

Хотя, вы действительно ошибаетесь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...