Что означает 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