"double* (*p[3]) (void* (*)());" 这个意思是什么?

8

我很难理解以下声明的含义。这个声明是否是标准的?

double* (*p[3]) (void* (*)());

有人能帮我理解这个声明的含义吗?


1
我很高兴踏入Java的世界... - Michael Laffargue
7
与在 C 世界中运行相比,是吗?;-) - Paul R
Oli Charlesworth 提供了一个通用有用的答案。不要关闭。 - DevSolar
应该将其关闭为重复问题,例如 https://dev59.com/6VjUa4cB1Zd3GeqPR4D1 - Paul R
5个回答

10

只需使用http://cdecl.org

声明 p 为指向返回指针的函数指针数组,该指针指向返回指向void类型指针的函数并返回指向double类型的指针。

有关更多信息,请参阅此 MSDN 文章:解释更复杂的声明符

但是,typedef 可以帮助:

typedef void *(*foo)();         // foo is a function-pointer type
typedef double *(*bar)(foo);    // bar is also a function-pointer type
bar p[3];

(显然,使用适当的名称替换foobar!)


2
我以前从来没见过那个网站 +1 - Hunter McMillen
1
在编程方面,将你的智慧之源链接出来比让它看起来像是你自己想出来的更好。;-) - DevSolar
@DevSolar - 不公平地假设 cdecl 是每个人理解看起来困难的 C 声明的唯一方式。 - ArjunShankar
在问题提出后的一分钟内就解决掉?这并不丢人,我认为我从来没有在没有 cdecl 的情况下解开过函数指针声明。 - DevSolar
@DevSolar:公平地说,一旦你记住了“算法”(如我链接的文章所述),手动完成这个过程就不是问题了。 - Oliver Charlesworth
这个网站真不错!将来会对很多人有帮助的 :-). - pacodelumberg

10

阅读复杂声明的规则:找到最左边的标识符并向外扩展,记住()[]*优先级更高,因此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 声明为一个由... 组成的数组,而不是一个返回 ... 的函数。

实际上这样的代码会是什么样子呢?首先,你需要三个函数指针。每个函数都接受一个参数,该参数是指向返回指针的函数的指针。
double *foo(void *(*)());
double *bar(void *(*)());
double *bletch(void *(*)());

double *(*p[3]) (void *(*)()) = {foo, bar, bletch};

每个foobarbletch都会调用传递给它的函数并以某种方式返回指向double的指针。
您还需要定义一个或多个函数,以满足每个foobarbletch的参数类型:
void *blurga() {...}

因此,如果您直接调用foo,则应按以下方式调用

double *pv;
...
pv = foo(blurga);

所以我们可以想象一下这样的调用:
double *pv = (*p[0])(blurga);


1 - 在函数参数声明的上下文中,T a[]T a[N]T *a 是相同的;在这三种情况下,aT 的指针,而不是 T 的数组。请注意,这仅适用于函数参数声明。因此,T *[] 将与 T ** 相同。


2
你的p是一个指向返回double指针的函数的3个指针数组,并且接受另一个返回void指针且不带参数的函数的指针作为参数。

但是,不要使用这种语法,尝试使用typedef代替。


我也是,但我喜欢Oli的链接,“像谚语一样教会了我如何钓鱼” :) - Dark Star1

1

这是一个大小为3的函数指针数组,返回指向double类型的指针,并以另一个函数指针作为参数。

可以存储在该数组中的函数指针类型为:double *(func)(void* (*)())
可以作为func参数传递的函数指针类型为:void *(func1)(void)


+1 是因为这是我最容易理解的描述。 - ArjunShankar

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接