Как интерпретировать сложные объявления, например:
int * (* (*fp1) (int) ) [10]; ---> declaration 1
int *( *( *[5])())(); --------> declaration 2
Есть ли какое-либо правило, которое следует соблюдать, чтобы понять приведенные выше объявления?
Как интерпретировать сложные объявления, например:
int * (* (*fp1) (int) ) [10]; ---> declaration 1
int *( *( *[5])())(); --------> declaration 2
Есть ли какое-либо правило, которое следует соблюдать, чтобы понять приведенные выше объявления?
Вот отличная статья о том, как читать сложные объявления в C: http://www.codeproject.com/KB/cpp/complex_declarations.aspx
Это очень помогло мне!
В частности - вы должны прочитать раздел "Правильное правило". Здесь цитата:
int * (* (* fp1) (int)) [10]; Это можно интерпретировать следующим образом:
- Начать с имени переменной -------------------------- fp1
- Ничего правильного, но), так что идите влево, чтобы найти * -------------- - указатель
- Выскочите из круглых скобок и встретитесь (int) --------- с функция, которая принимает int как аргумент
- Идите влево, найдите * ---------------------------------------- и верните указатель
- Скопируйте скобки в скобки, идите направо и нажмите [10] -------- на массив 10
- Идите влево, найдите * ----------------------------------------- указатели на
- Идите влево, найдите int -------------------------------- ints.
Вы можете использовать cdecl
*
:
cdecl> explain int *( *( *a[5])())();
declare a as array 5 of pointer to function
returning pointer to function returning pointer to int
cdecl> explain int * (* (*fp1) (int) ) [10];
declare fp1 as pointer to function (int) returning
pointer to array 10 of pointer to int
*
Связанный - это веб-сайт, который использует этот инструмент командной строки в бэкэнд.
Я уже давно изучил следующий метод:
Начните с идентификатора типа (или внутренней скобки) и перемещайтесь по спирали, беря элемент справа вначале
В случае
int * (* (*fp1) (int) ) [10];
Вы можете сказать:
Результат:
fp1 является указателем на функцию, принимающую int и возвращающую указатель на массив из 10 указателей на int
Рисунок фактической спирали (в вашем уме, по крайней мере) помогает много.
Для решения этих сложных заявлений необходимо иметь в виду правило, что приоритет функции-вызова operator() и оператора индекса массива [] выше, чем оператор разыменования *. Очевидно, скобка() может использоваться для переопределения этих приоритетов.
Теперь выполните свое объявление из середины, что означает имя идентификатора.
int * (* (* fp1) (int)) [10]; --- > декларация 1
В соответствии с приведенным выше правилом приоритетов вы можете легко понять это, разбив декларацию как
fp1 * (int) * [10] * int
и читайте его прямо слева направо на английском языке как "fp1 - это указатель на функцию, принимающую int и возвращающую указатель на массив [10] указателей на int". Обратите внимание, что объявление разбивается таким образом, чтобы понять его вручную. Компилятору не нужно анализировать его таким образом.
Аналогично,
int * (* (* [5])())(); -------- > Объявление 2
нарушается как
[5] *() *() * int
Итак, он объявляет "массив [5] указателей типа функции(), который возвращает указатель на функцию(), которая, в свою очередь, возвращает указатель на int".
Хотя уже был дан ответ, но вы также можете прочитать эту статью:
Начните с самого левого идентификатора и проведите свой путь, вспомнив, что отсутствовала какая-либо явная группировка []
и ()
bind перед *
, например:
*a[] -- is an array of pointer (*a)[] -- is a pointer to an array *f() -- is a function returning pointer (*f)() -- is a pointer to a function
Таким образом, мы читаем int *(*(*fp1)(int))[10]
как:
fp1 -- fp1
*fp1 -- is a pointer
(*fp1)(int) -- to a function
taking an int parameter
*(*fp1)(int) -- returning a pointer
(*(*fp1)(int))[10] -- to a 10-element array
*(*(*fp1)(int))[10] -- of pointer
int *(*(*fp1)(int))[10] -- to int
Объявление int *(*(*[5])())()
представляет собой немного сложную задачу, поскольку нет идентификатора; вы обычно видите это в объявлениях функций, где параметр имеет такой тип:
void foo(int *(*(*[5])())(), double);
Это тот же принцип, что и неменованный int
параметр в объявлении fp1
. Массив дает нам ключ, вы также можете искать самую левую внутреннюю группировку круглых скобок.
-- unnamed
[5] -- is a 5-element array ([] binds before *)
*[5] -- of pointers
(*[5])() -- to functions
*(*[5])() -- returning pointers
(*(*[5])())() -- to functions
*(*(*[5])())() -- returning pointers
int *(*(*[5])())() -- to int
По часовой стрелке/спирали:
* http://c-faq.com/decl/spiral.anderson.html