Спиральное правило и "объявление следует за использованием" для синтаксического анализа объявлений C и С++

Этот вопрос следует этому другому вопросу о декларировании C. Читая ответ на этот вопрос, я прочитал о спиральном правиле, и я также понял, что означает "объявление после использования".

Хорошо. Но затем я прочитал это объявление:

char *(*(*a[N])())(); 

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

Что я читаю:

(*(*a[N])()) 

является функцией (), возвращающей a char *, затем разыменовывая следующую

(*a[N])() // 1

- это 'функция, возвращающая char*', и поэтому 1 является "указателем на функцию, возвращающую char *", то я бы сказал: "Когда вызывается (*a[N]), это [предыдущая декларация]". На этом этапе (*a[N]) является функцией, возвращающей указатель на функцию, возвращающую char *.

Но тогда я не знаю, как применить это правило, чтобы различать "указатель на массив" и "массив указателя".

Может ли кто-нибудь прояснить это?

Другой вопрос: каковы правила "приоритета" в таких объявлениях, между & (в С++), * и []? [возможно, "приоритет" не является правильным термином]


Чтобы проверить, правильно ли я понял "правило спирали", я также разбираю это выражение ниже; скажите, пожалуйста, если я ошибаюсь.

       +-----------+
       | +------+  |
       | | +-+  |  |
       | | ^ |  |  |
char* (*(* a[N])())(); 
    ^  ^ ^   ^  ^  ^
    |  | |   |  |  |
    |  | +---+  |  |
    |  +--------+  |
    +--------------+

Для меня проще (цикл за циклом):

  • a - массив из N...
  • указатель на функцию возврата...
  • указатель на функцию возврата...
  • char *

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

Ответ 1

Вам просто нужно создать его пошагово.

char *X();  // X =~ (*(*a[N])())

Возвращаемая функция char*

char *(*Y())();  // Y =~ (*a[N])

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

В объявлении, как и в выражении (объявление следует использовать), postfix [] имеет более высокий приоритет, который унарный *, поэтому *a[N] эквивалентен *(a[N]), а не (*a)[N].

char *(*(*Z)())();  // Z =~ a[N]

Указатель на функцию, возвращающую указатель на функцию, возвращающую char*.

char *(*(*a[N])())();

Массив из N указателей на функции, возвращающие указатель на возвращаемую функцию char*.