Как вы объявляете указатель на функцию, которая возвращает указатель на массив значений int в C / C ++? - PullRequest
9 голосов
/ 05 августа 2010

Это правильно?

int (*(*ptr)())[];

Я знаю, что это тривиально, но я смотрел на старый тест об этих видах конструкций, и эта конкретная комбинация не была на тесте, и она действительно ведетя сумасшедший;Я просто должен убедиться.Есть ли ясные и твердые понятные правила для таких заявлений?(т.е.: указатель на ... массив ... указателей на ... функции, которые .... и т. д.) Спасибо!

R

Ответы [ 6 ]

14 голосов
/ 05 августа 2010

Правое лево-правило облегчает задачу.

int (*(*ptr)())[]; можно интерпретировать как

Начните с имени переменной ------------------------------- ptr

Ничего направо, кроме ), поэтому идите налево, чтобы найти * -------------- - указатель

Выпрыгнуть из скобок и встретить () ----------- с функцией, которая не принимает аргументов (в случае неопределенного количества C аргументов)

Идите налево, найдите * ---------------------------------------- -------- и возвращает указатель

Поставьте скобки, пройдите направо и нажмите [] ---------- до массива

Снова налево, найдите int ------------------------------------- ints.

6 голосов
/ 05 августа 2010

Почти во всех ситуациях, когда вы хотите вернуть указатель на массив, самое простое, что нужно сделать, это вернуть указатель на первый элемент массива.Этот указатель может использоваться в тех же контекстах, что и имя массива, и обеспечивает не более или менее косвенную ссылку, чем возвращение указателя типа «указатель на массив», в действительности он будет содержать то же значение указателя.

Если вы следуетеэто вам нужен указатель на функцию, возвращающую указатель на int.Вы можете создать это (создание объявлений проще, чем анализ).

Указатель на int:

int *A;

Функция, возвращающая указатель на int:

int *fn();

указатель на функцию, возвращающую указатель на int:

int *(*pfn)();

Если вы действительно хотите вернуть указатель на функцию, возвращающую указатель на массив int, вы можете следоватьтот же процесс.

Массив int:

int A[];

Указатель на массив int:

int (*p)[];

Функция, возвращающая указатель ...:

int (*fn())[];

Указатель на fn ...:

int (*(*pfn)())[];

что у вас есть.

2 голосов
/ 05 августа 2010

Ты не.Просто разделите его на две typedef: одну для указателя на массив int и одну для указателя на функции.Что-то вроде:

typedef int (*IntArrayPtr_t)[];
typedef IntArrayPtr_t (*GetIntArrayFuncPtr_t)(void);

Это не только более читабельно, но и упрощает объявление / определение функций, которым вы собираетесь назначить переменную:

IntArrayPtr_t GetColumnSums(void)
{ .... }

Конечноэто предполагает, что это была реальная ситуация, а не вопрос интервью или домашнее задание.Я бы все еще утверждал, что это лучшее решение для этих случаев, но это только я.:)

1 голос
/ 05 августа 2010

Если вы хотите обмануть:

typedef int(*PtrToArray)[5];
PtrToArray function();

int i = function;

Компиляция этого на gcc дает: invalid conversion from 'int (*(*)())[5]' to 'int'. Первый бит - это тип, который вы ищете.

Конечно, когда у вас есть PtrToArray typedef, все упражнение становится довольно тривиальным, но иногда это бывает полезно, если у вас уже есть имя функции и вам просто нужно где-то его вставить. И по какой-то причине вы не можете полагаться на хитрость шаблонов, чтобы скрыть кровавые подробности от вас.

Если ваш компилятор поддерживает это, вы также можете сделать это:

typedef int(*PtrToArray)[5];
PtrToArray function();

template<typename T> void print(T) {
    cout << __PRETTY_FUNCTION__ << endl;
}

print(function);

Который на моем компьютере выдает void function(T) [with T = int (* (*)())[5]]

Возможность читать типы довольно полезна, поскольку понимание ошибок компилятора часто зависит от вашей способности выяснить, что означают все эти скобки. Но делать их самостоятельно менее полезно, ИМО.

0 голосов
/ 05 августа 2010

Используя cdecl, вы получите следующее

cdecl> declare a as pointer to function returning pointer to  array of int;
Warning: Unsupported in C -- 'Pointer to array of unspecified dimension'
    (maybe you mean "pointer to object")
int (*(*a)())[]

Этот вопрос из C-faq похож, но предоставляет 3 подхода для решения проблемы.

0 голосов
/ 05 августа 2010

Вот мое решение ...

int** (*func)();

Функтор, возвращающий массив int *.Это не так сложно, как ваше решение.

...