Я просто просматривал какой-то код в Интернете и нашел это:
float * (*(*foo())[SIZE][SIZE])()
Как мне прочитать это объявление? Существует ли определенный набор правил для чтения таких сложных объявлений?
Я просто просматривал какой-то код в Интернете и нашел это:
float * (*(*foo())[SIZE][SIZE])()
Как мне прочитать это объявление? Существует ли определенный набор правил для чтения таких сложных объявлений?
Я не сделал этого через некоторое время!
Начните с foo
и идите направо.
float * (*(*
<суб > foo()
суб > )[SIZE][SIZE])()
foo - это функция без аргументов...
Не может идти правильно, так как есть закрывающая скобка. Идите влево:
float * (*(
<суб > * foo()
суб > )[SIZE][SIZE])()
foo - это функция без аргументов, возвращающая указатель
Нельзя идти дальше, так что давайте пересечь круглые скобки и снова идем вправо
float * (*
<суб > (* foo())
суб > [SIZE][SIZE])()
float * (*
<суб > (* foo())[SIZE]
суб > [SIZE])()
float * (*
<суб > (* foo())[SIZE][SIZE]
суб > )()
foo - это функция без аргументов, возвращающая указатель на массив массивов SIZE из SIZE...
Достигнутая закрывающая скобка, снова оставлена для достижения символа указателя:
float * (
<суб > *(* foo())[SIZE][SIZE]
суб > )()
foo - это функция без аргументов, возвращающая указатель на массив массивов SIZE указателей SIZE для...
Левая скобка снова, поэтому мы пересекаем ее и снова идем вправо:
float *
<суб > ( *(* foo())[SIZE][SIZE])
суб > ()
float *
<суб > ( *(* foo())[SIZE][SIZE])()
суб >
foo - это функция без аргументов, возвращающая указатель на массив массивов SIZE указателей SIZE на функцию без аргументов...
И осталось до конца
<суб > float * ( *(* foo())[SIZE][SIZE])()
суб >
foo - это функция без аргументов, возвращающая указатель на массив массивов SIZE указателей SIZE на функцию без аргументов, возвращающую указатель на float
И кто бы ни написал это, пожалуйста, научите его использовать typedef
:
// Function that returns a pointer to float
typedef float* PFloatFunc ();
// Array of pointers to PFloatFunc functions
typedef PFloatFunc* PFloatFuncArray2D[SIZE][SIZE];
// Function that returns a pointer to a PFloatFuncArray2D
PFloatFuncArray2D* foo();
Стандартное правило: найдите самый левый идентификатор и проведите свой путь, вспомнив, что []
и ()
связывают до *
:
foo -- foo
foo() -- is a function
*foo() -- returning a pointer
(*foo())[SIZE] -- to a SIZE-element array
(*foo())[SIZE][SIZE] -- of SIZE-element arrays
*(*foo())[SIZE][SIZE] -- of pointers
(*(*foo())[SIZE][SIZE])() -- to functions
* (*(*foo())[SIZE][SIZE])() -- returning pointers
float * (*(*foo())[SIZE][SIZE])(); -- to float
Итак, представьте, что у вас есть куча функций, возвращающих указатели на float
:
float *quux();
float *bar();
float *bletch();
float *blurga();
Скажем, вы хотите сохранить их в таблице 2x2:
float *(*tab[SIZE][SIZE])() = {quux, bar, bletch, blurga};
tab
представляет собой массив SIZE x SIZE указателей на функции, возвращающие указатели на float
.
Теперь давайте решим, что мы хотим, чтобы функция возвращала указатель на эту таблицу:
float *(*(*foo())[SIZE][SIZE])()
{
static float *(*tab[SIZE][SIZE])() = {quux, bar, bletch, blurga};
return &tab;
}
Обратите внимание, что у вас может быть несколько функций, которые строят таблицы разных функций или организуют одни и те же функции по-разному:
float *(*(*qwerbl())[SIZE][SIZE])()
{
static float *(*tab[SIZE][SIZE])() = {blurga, bletch, bar, quux};
return tab;
}
что является единственной причиной, по которой я могу придумать что-то подобное. Вы не должны часто видеть подобные типы в дикой природе (хотя иногда они возникают, и я был виновен в написании чего-то подобного ужасного).
Согласно cdecl.org
объявить foo как функцию, возвращающую указатель на массив SIZE массива SIZE указателя на функцию, возвращающую указатель на float
Используйте правило спирали, данное Luchian Grigore, если вы хотите его декодировать вручную.
Лучшее, что можно сделать здесь, это преобразовать в серию typedefs.
typedef float * fnReturningPointerToFloat();
typedef fnReturningPointerToFloat* fnArray[SIZE][SIZE];
fnArray* foo();
Как правило, вы можете попробовать cdecl.org, но вам нужно заменить SIZE
Скажите, что вы заменили SIZE
на 12, вы получите:
объявить foo как функцию, возвращающую указатель на массив 12 массива 12 из указатель на функцию, возвращающую указатель на float
Я не уверен, что это действительно помогает!
Два наблюдения здесь:
Этот документ дает мне лучший ключ о том, как легко подготовить любое объявление C:
http://c-faq.com/decl/spiral.anderson.html
Существует три простых шага:
Начиная с неизвестного элемента, двигайтесь по спирали/по часовой стрелке; при замене следующих элементов замените их соответствующими английскими утверждениями:
[X]
или[]
= > Array X size of... или Array undefined размер...
(type1, type2)
= > функция, передающая тип1 и возвращаемый тип2...
*
= > указатель для...Продолжайте делать это по спирали/по часовой стрелке до тех пор, пока все маркеры не будут закрыты.
Сначала сначала разрешайте что-либо в скобках!
Пример:
+-------+
| +-+ |
| ^ | |
char *str[10];
^ ^ | |
| +---+ |
+-----------+
Question we ask ourselves: What is str?
``str is an...
- We move in a spiral clockwise direction starting with `str' and the first character we see is a `[' so, that means we have an array, so...
``str is an array 10 of...
- Continue in a spiral clockwise direction, and the next thing we encounter is the `*' so, that means we have pointers, so...
``str is an array 10 of pointers to...
- Continue in a spiral direction and we see the end of the line (the `;'), so keep going and we get to the type `char', so...
``str is an array 10 of pointers to char''
We have now ``visited'' every token; therefore we are done!
объявить foo как функцию, возвращающую указатель на массив SIZE массива SIZE указателя на функцию, возвращающую указатель на float