Сложные декларации с


Я просто нашла код в интернете и нашел это:

float * (*(*foo())[SIZE][SIZE])()

Как я могу прочитать эту декларацию? Есть определенный набор правил для чтения таких сложных деклараций?

7 69

7 ответов:

я давно этого не делал!

Начнем с foo и идем направо.

float * (*(*foo())[SIZE][SIZE])()

Foo-это функция без аргументов...

не могу идти направо, так как есть закрывающая скобка. Идите налево:

float * (*(* foo())[SIZE][SIZE])()

foo-это функция без аргументов, возвращающих a указатель

дальше налево идти нельзя, так что давайте скрестим скобки и снова направо

float * (*(* foo())[SIZE][SIZE])() float * (*(* foo())[SIZE][SIZE])() float * (*(* foo())[SIZE][SIZE])()

Foo-это функция без аргументов, возвращающая указатель на массив массивов размера ...

закрывающая скобка достигнута, снова влево, чтобы достичь указателя символ:

float * (*(* foo())[SIZE][SIZE])()

foo-это функция без аргументов, возвращающая указатель на массив размерных массивов указателей на размер ...

снова левая скобка, поэтому мы пересекаем ее и снова идем направо:

float *( *(* foo())[SIZE][SIZE])() float *( *(* foo())[SIZE][SIZE])()

Foo-это функция без аргументов, возвращающая указатель на целое массив размера массивы указателей размера на функцию без аргументов...

и до конца

float * ( *(* foo())[SIZE][SIZE])()

foo-это функция без аргументов, возвращающая указатель на массив размера массивы указателей размера на функцию без аргументов, возвращающих указатель на 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();

стандартное правило: найти самый левый идентификатор и работать ваш выход, помня, что [] и () bind перед *:

            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 представляет собой размер X размер массива указателей на функции, возвращающие указатели на 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 как функцию, возвращающую указатель на размер массива размера массива указатель на функцию, возвращающую указатель на float

используйте спиральное правило, данное Лучианом Григоре, если вы хотите декодировать его вручную.

лучшее, что можно здесь сделать-это преобразовать в ряд типов.

typedef float * fnReturningPointerToFloat();
typedef fnReturningPointerToFloat* fnArray[SIZE][SIZE];
fnArray* foo();

Как правило, вы можете попробовать cdecl.org но вам нужно будет заменить SIZE

скажем, вы меняетесь SIZE для 12, вы получите:

объявить foo как функцию, возвращающую указатель на массив 12 массива 12 из указатель на функцию, возвращающую указатель на float

Я не уверен, что действительно поможет вам!

два наблюдения здесь:

  1. я предполагаю, что этот код не имел комментария рядом с ним объясняя, какова его цель (т. е. не техническое объяснение того, что это такое, а то, что он достигает с функциональной / бизнес-точки зрения) если программист должен использовать что-то столь сложное, как это, они должны быть достаточно хороши, чтобы объяснить будущим сопровождающим, какой цели он служит.
  2. конечно, в C++ есть более очевидные и, вероятно, более безопасные способы достижения того же самого.

этот документ дает мне лучшую подсказку о том, как легко подготовить любую декларацию C :

http://c-faq.com/decl/spiral.anderson.html

есть три простых шага, чтобы следовать:

  • начиная с неизвестного элемента, двигайтесь по спирали / по часовой стрелке; при ecounting следующие элементы заменяют их соответствующими английскими утверждениями:

    • [X] или [] => массив X размер ... или массив неопределенного размера ...

    • (type1, type2) = > функция передачи type1 и type2 возвращения ...

    • * => указатель(ы) на ...

  • продолжайте делать это по спирали / по часовой стрелке, пока все маркеры не будут покрыты.

  • всегда решать что-нибудь в скобках в первую очередь!

пример :

             +-------+
             | +-+   |
             | ^ |   |
        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!

от http://cdecl.org/

объявить foo как функцию, возвращающую указатель на размер массива размер массива указателя на функцию, возвращающую указатель на float