尚不完全清楚您要完成什么,因此我将介绍不止一种可能性。
首先,复习一下如何在 C 中读写复杂的声明:
记住() 和[] 的优先级高于一元*,所以*a[] 是一个指针数组,而(*a)[] 是一个指向数组;同样,*f() 是一个返回指针的函数,而(*f)() 是一个指向函数的指针。
当你试图阅读一个毛茸茸的声明时,从最左边的标识符开始,然后记住上面的规则。因此,
int (*(x)())[2];
读作
x -- x
(x) -- x
(x)() -- is a function
*(x)() -- returning a pointer
(*(x)())[2] -- to a 2-element array
int (*(x)())[2] -- of int
在这种情况下,x 周围的括号是多余的,可以删除:int (*x())[2];。
以下是如何编写和使用这样的函数:
int (*x())[2]
{
int (*arr)[2] = malloc(sizeof *arr); // alternately, you could simply write
return arr; // return malloc(sizeof (int [2]));
} // type of *arr == int [2]
int main(void)
{
int (*p)[2] = NULL; // alternately, you could write
... // int (*p)[2] = x();
p = x();
...
free(p);
}
注意arr、p 和x() 的声明看起来都一样——它们都符合int (*_)[2]; 的模式。 这很重要。如果您将一件事声明为T (*p)[N],将另一件事声明为T **q,那么它们的类型不同并且可能不兼容。指向T 数组的指针与指向T 的指针的类型不同。
如果您的目标是创建一个指向返回int 的函数 的指针数组,那么您的类型将类似于int (*f[2])();,其内容为
f -- f
f[2] -- is a 2-element array
*f[2] -- of pointers
(*f[2])() -- to functions
int (*f[2])(); -- returning int
看起来像下面这样:
int foo() {...}
int bar() {...}
int main(void)
{
int (*f[2])() = {foo, bar};
...
}
如果你想要一个返回f 的函数,那就有点棘手了。 C 函数不能返回数组类型;它们只能返回指向数组的指针,因此您的函数声明将被构建为
g -- g
g() -- is a function
*g() -- returning a pointer
(*g())[2] -- to a 2-element array
*(*g())[2] -- of pointers
(*(*g())[2])() -- to functions
int (*(*g())[2])() -- returning int
这样的野兽会被这样使用:
int foo() {...}
int bar() {...}
int (*(*g())[2])()
{
int (*(*f)[2])() = malloc(sizeof *f);
(*f)[0] = foo; // the type of the *expressions* foo and bar
(*f)[1] = bar; // is `int (*)()`, or pointer to function
return f; // returning int
}
int main(void)
{
int (*(*p)[2])();
int x, y;
...
p = g();
x = (*(*p)[0])();
y = (*(*p)[1])();
...
free(p);
...
}
请注意,您还可以使用替换方法从外向内构建毛茸茸的声明。所以,
int x(); -- x is a function returning int
int (*p)(); -- replace x with (*p) to get a pointer to a function
returning int
int (*a[2])(); -- replace p with a[2] to get an array of pointers
to functions returning int
int (*(*q)[2])(); -- replace a with (*q) to get a pointer to an array
of pointers to functions returning int
int (*(*g())[2])(); -- replace q with g() to get a function returning
a pointer to an array of pointers to functions
returning int.
相同的结果,不同的路径。我更喜欢第一种方法,但任何一种都应该有效。
许多人建议使用typedef 使内容更易于阅读:
typedef int ifunc(); // ifunc is a synonym for "function returning int"
typedef ifunc *pifunc; // pifunc is a synonym for "pointer to function
// returning int
typedef pifunc farr[2]; // farr is a synonym for "2-element array of
// pointer to function returning int
typedef farr *pfarr; // pfarr is a synonym for "pointer to 2-element
// array of pointer to function returning int
pfarr g()
{
pfarr f = malloc(sizeof *f);
(*f)[0] = foo;
(*f)[1] = bar;
return f;
}
int main(void)
{
pfarr p = g();
int x, y;
x = (*(*p)[0])();
y = (*(*p)[1])();
...
}
是的,声明更容易阅读,但p 的声明和(*(*p)[1])() 的表达式之间没有联系。你必须通过所有的typedefs 来理解为什么这个表达式是这样写的,为每个typedef 建立一个心理地图。
是的,int (*(*g())[2])() 之类的声明旨在让您目不暇接,将所有内容隐藏在 typedef 后面会使 IMO 情况变得更糟。