我需要声明一个指向函数的指针数组,如下所示:
extern void function1(void);
extern void function2(void);
...
void (*MESSAGE_HANDLERS[])(void) = {
function1,
function2,
...
};
但是,我希望将数组声明为常量 - 数组中的数据和指向数据的指针。不幸的是,我不记得在哪里放置const关键词。
我假设在这种情况下实际指针MESSAGE_HANDLERS已经是常量,因为它被声明为数组。另一方面,如果声明如图所示,那么数组中的函数指针是否可以在运行时更改?
答案 0 :(得分:56)
有一种技术可以记住如何构建这种类型。首先尝试从名称开始读取指针并从右向左阅读。
T t[5];
是5 T 的数组。要使T成为函数类型,请将返回类型写入左侧,将参数写入右侧:
void t[5](void);
是一个包含5个函数的数组,返回void且不带参数。但是函数本身不能填充数组!它们不是对象。只有指向它们的指针才可以。
怎么样?
void * t[5](void);
这仍然是错误的,因为它只会将返回类型更改为指向void的指针。你必须使用括号:
void (*t[5])(void);
这实际上会有效。 t是一个包含5个指向函数的数组,这些函数返回void并且不带参数。
大!一系列指向阿拉斯的指针怎么样?这非常相似。元素类型显示在左侧,维度显示在右侧。同样,需要括号,因为否则数组将成为整数指针的多维数组:
int (*t[5])[3];
就是这样!一个5 em指向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];
这是一个函数,它使int返回一个指向函数的指针,bool返回一个指向3 int 的数组的指针
既然上面已经解释了如何从基本类型构建复杂类型,您可以将const
放在您现在知道它们所属位置的位置。请考虑一下:
T c * c * c ... * c name;
T
是我们最后指向的基本类型。 c
代表const或not 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声明函数和数组的方式实际上实际上有点令人困惑。你必须首先考虑它,但如果你理解它,你可以使用它编写非常紧凑的函数声明。
答案 1 :(得分:15)
在这种情况下,执行typedef
来命名您的函数签名,这样可以简化:
typedef void MESSAGE_HANDLER(void);
有了它,它应该只是:
MESSAGE_HANDLER * const handlers[] = { function1, function2 };
使数组的实际内容保持不变。
编辑:从typedef
删除了指针部分,这确实更好(实时和学习)。
答案 2 :(得分:15)
cdecl
说:
cdecl> explain void (* const foo[])(void)
declare foo as array of const pointer to function (void) returning void
这是你需要的吗?
答案 3 :(得分:1)
使用Visual Studio 2008,我得到:
void (* const MESSAGE_HANDLERS[])(void) = {
NULL,
NULL
};
int main ()
{
/* Gives error
'=' : left operand must be l-value
*/
MESSAGE_HANDLERS = NULL;
/* Gives error
l-value specifies const object
*/
MESSAGE_HANDLERS[0] = NULL;
}
答案 4 :(得分:1)
我不确定这是否适用于'C'。它确实在'C ++'中起作用:
首先将MESSAGE_HANDLERS定义为类型:
typedef void (*MESSAGE_HANDLER)();
然后,使用类型定义将数组声明为常量:
MESSAGE_HANDLER const handlers[] = {function1, function2};
诀窍在于typedef
,如果你可以在'C'语义上做同样的事情,它也应该有效。