Что означает double* (*p[3]) (void* ( * ) ());?
Мне трудно понять, что означает следующее объявление. Это заявление стандартные?
double* (*p[3]) (void* (*)());
может ли кто-нибудь помочь мне понять смысл этого заявления?
5 ответов
правило для чтения волосатых деклараций: найдите самый левый идентификатор и работайте наружу, помня, что ()
и []
bind перед *
, так что T *a[N]
представляет собой массив указателей на T
, T (*a)[N]
является указателем на массив T
, T *f()
- это функция, возвращающая указатель на T
и T (*f)()
является указателем на функцию, возвращающую T. поскольку прототип функции может опустить имена параметров, вы можете увидеть такие вещи, как T *[N]
или T (*)()
. Смысл в основном же1, просто представьте, что есть идентификатор длины 0.
таким образом,
p -- p
p[3] -- is a 3-element array
*p[3] -- of pointers
(*p[3]) ( ) -- to functions
(*p[3]) ( (*)()) -- taking a pointer to a function
(*p[3]) ( * (*)()) -- returning a pointer
(*p[3]) (void* (*)()) -- to void
* (*p[3]) (void* (*)()) -- returning a pointer
double* (*p[3]) (void* (*)()); -- to double
самое главное, чтобы забрать здесь, что вы объявляете p
как массив of ...
, а не функция, возвращающая ...
.
как бы такой зверь выглядел на практике? Ну, во-первых, вам нужно указать на три функции. Каждая из этих функций принимает один параметр, который является указателем на функцию возврат указателя на void:
double *foo(void *(*)());
double *bar(void *(*)());
double *bletch(void *(*)());
double *(*p[3]) (void *(*)()) = {foo, bar, bletch};
каждого foo
, bar
и bletch
вызовет переданную ему функцию и каким-то образом вернет указатель на double
.
вы также хотите определить одну или несколько функций, удовлетворяющих типу параметра для каждого из foo
, bar
и bletch
:
void *blurga() {...}
Итак, если вы позвонили foo
напрямую, вы бы назвали это как
double *pv;
...
pv = foo(blurga);
таким образом, мы могли бы представить себе вызов как
double *pv = (*p[0])(blurga);
1 - разница в том, что в объявлении параметра функции
T a[]
и T a[N]
идентичны T *a
; во всех трех случаях a
это указатель T
, а не массив T
. Обратите внимание, что это только true в объявлении параметра функции. Таким образом, T *[]
будет идентично T **
.просто используйте http://cdecl.org:
объявить p как массив 3 указателя на функцию (указатель на функцию, возвращающий указатель на void), возвращающий указатель на double
для получения дополнительной информации см. Эту статью MSDN:интерпретация более сложных деклараторов.
но typedefs поможет:
typedef void *(*foo)(); // foo is a function-pointer type
typedef double *(*bar)(foo); // bar is also a function-pointer type
bar p[3];
(очевидно, используйте соответствующие имена вместо foo
и bar
!)
код p
Это массив из 3 указателей функции возврат double
указатель, и принимает в качестве аргумента указатель на другую функцию, которая возвращает void
указатель, и это не требует аргументов.
а, не используйте этот синтаксис, попробуйте вместо этого использовать typedef.
это массив (размера 3) указателей функций, который возвращает указатель на double и принимает другой указатель функции в качестве аргумента.
тип функции, указатель которой может быть сохранен в массиве:double *(func)(void* (*)())
Тип функции, указатель на которую можно передать в качестве аргумента func:void *(func1)(void)
"существует метод, известный как" правило по часовой стрелке/спирали", который позволяет любому программисту c анализировать в своей голове любое объявление C!"
По Спирали Правило - http://c-faq.com/decl/spiral.anderson.html