有一种技术可以记住如何构建这种类型。首先尝试从名称开始读取指针,并从右向左读取。
如何在没有帮助的情况下声明这些东西?
数组
T t[5];
是一个 5 个 T 的数组。要使 T 成为函数类型,请将返回类型写在左边,将参数写在右边:
void t[5](void);
将是一个返回 void 且不带参数的 5 个函数的数组。但是函数本身不能塞进数组中!它们不是对象。只有指向它们的指针可以。
怎么样
void * t[5](void);
这仍然是错误的,因为它只会将返回类型更改为指向 void 的指针。您必须使用括号:
void (*t[5])(void);
这实际上会起作用。 t 是一个包含 5 个指针的数组,指向返回 void 且不带参数的函数。
太棒了!指向 arras 的指针数组呢?这非常相似。元素类型显示在左侧,尺寸显示在右侧。同样,需要括号,否则数组将成为整数指针的多维数组:
int (*t[5])[3];
就是这样! 一个由 5 个指针组成的数组,指向 3 个 int 的数组。
函数呢?
我们刚刚学到的关于函数的知识也是正确的。让我们声明一个带有 int 的函数,它返回指向另一个不带参数并返回 void 的函数的指针:
void (*f(int))(void);
出于与上述相同的原因,我们再次需要括号。我们现在可以调用它,并再次调用返回的函数指向。
f(10)();
返回一个指向函数的指针返回另一个指向函数的指针
这个呢?
f(10)(true)(3.4);
?换句话说,一个采用 int 的函数返回一个指向一个采用 bool 的函数的指针返回一个指向一个采用 double 并返回 void 的函数的指针的函数会是什么样子?答案是你只是嵌套它们:
void (*(*f(int))(bool))(double);
你可以无休止地这样做。实际上,您也可以返回指向数组的指针,就像返回指向函数的指针一样:
int (*(*f(int))(bool))[3];
这是一个函数,返回一个指向函数的指针,返回一个指向一个函数的函数,返回一个指向 3 个 int 数组的指针
和 const 有什么关系?
现在上面解释了如何从基本类型构建更复杂的类型,您可以将const 放在您现在知道它们所属的位置。考虑一下:
T c * c * c ... * c name;
T 是我们最后指向的基本类型。 c 代表 const 或非 const。例如
int const * const * name;
将声明 name 的类型为 指向一个常量指针的指针,该指针指向一个常量 int。可以更改name,但不能更改*name,类型为
int const * const
也不是**name,它的类型是
int const
让我们把它应用到上面的函数指针上:
void (* const t[5])(void);
这实际上会声明数组包含常量指针。所以在创建(和初始化)数组之后,指针是常量,因为const出现在星号之后。请注意,在这种情况下,我们不能在星号之前放置const,因为没有指向常量函数的指针。函数根本不能是 const ,因为那没有意义。因此以下内容无效:
void (const * t[5])(void);
结论
C++ 和 C 声明函数和数组的方式实际上有点令人困惑。您必须首先了解它,但如果您理解它,您可以使用它编写非常紧凑的函数声明。