如何在C中声明常量函数指针数组?
我需要声明一个指向函数的指针数组,如下所示:如何在C中声明常量函数指针数组?,c,arrays,pointers,constants,function-pointers,C,Arrays,Pointers,Constants,Function Pointers,我需要声明一个指向函数的指针数组,如下所示: extern void function1(void); extern void function2(void); ... void (*MESSAGE_HANDLERS[])(void) = { function1, function2, ... }; 但是,我希望数组被声明为常量——数组中的数据和指向数据的指针。不幸的是,我不记得在哪里放置const关键字 我假设实际指针,即本例中的MESSAGE_HANDLERS,已经是常
extern void function1(void);
extern void function2(void);
...
void (*MESSAGE_HANDLERS[])(void) = {
function1,
function2,
...
};
但是,我希望数组被声明为常量——数组中的数据和指向数据的指针。不幸的是,我不记得在哪里放置const关键字
我假设实际指针,即本例中的MESSAGE_HANDLERS,已经是常量,因为它被声明为数组。另一方面,如果数组中的函数指针是如图所示声明的,那么它在运行时难道不能更改吗?在这种情况下,请使用
typedef
来命名函数签名,这会使它简单得多:
typedef void MESSAGE_HANDLER(void);
有了这一点,就应该:
MESSAGE_HANDLER * const handlers[] = { function1, function2 };
获取数组常量的实际内容
编辑:从
typedef
中删除了指针部分,这确实更好(实时学习)。使用VisualStudio 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;
}
cdecl
说:
cdecl> explain void (* const foo[])(void)
declare foo as array of const pointer to function (void) returning void
这是您需要的吗?我不确定这在“C”中是否有效。它在“C++”中确实有效:
- 首先将消息处理程序定义为一种类型:
typedef void(*MESSAGE_HANDLER)()代码>
- 然后,使用类型定义将数组声明为常量:
MESSAGE_HANDLER const handlers[]={function1,function2}代码>
诀窍在于
typedef
,如果你能在“C”中做同样的语义,它也应该能工作。有一种技巧可以记住如何构建这样的类型。首先,尝试从指针的名称开始读取指针,然后从右向左读取
如何在没有帮助的情况下申报这些东西?
阵列
是一个5 T的数组。要使T成为函数类型,请在左侧写入返回类型,在右侧写入参数:
void t[5](void);
将是一个由5个函数组成的数组,返回void,不带参数。但是函数本身不能填充在数组中!它们不是物体。只有指向它们的指针可以
那怎么办
void * t[5](void);
这仍然是错误的,因为它只会将返回类型更改为指向void的指针。必须使用括号:
void (*t[5])(void);
这实际上是可行的。t是一个由5个指针组成的数组,指向返回void且不带参数的函数
太好了!那么一个指向arras的指针数组呢?这很相似。元素类型显示在左侧,尺寸标注显示在右侧。同样,需要括号,否则数组将成为整数指针的多维数组:
int (*t[5])[3];
就这样!指向3 int数组的5个指针数组
功能呢?
我们刚刚学到的关于函数的知识也是正确的。让我们声明一个接受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的函数,返回指向3 int数组的指针
这和const有什么关系?
既然上面解释了如何从基本类型构建complexer类型,您可以将const
放在您现在知道它们所属的位置。试想一下:
T c * c * c ... * c name;
T
是我们最后指向的基本类型。c
表示常量或非常量。比如说
int const * const * name;
将声明名称以使类型指针指向常量int。您可以更改名称
,但不能更改*名称
,该类型为
int const * const
int const
也不是**name
,类型为
int const * const
int const
让我们将其应用于上面的函数指针:
void (* const t[5])(void);
这实际上会声明数组包含常量指针。因此,在创建(并初始化)数组之后,指针是常量,因为常量出现在星号之后。请注意,在这种情况下,我们不能将常量
放在星号之前,因为没有指向常量函数的指针。函数不能是常量,因为这没有意义。因此,以下内容无效:
void (const * t[5])(void);
结论
C++和C的声明函数和数组的方式实际上是有点混乱。您必须首先了解它,但如果您理解它,您可以使用它编写非常紧凑的函数声明。
是的,这正是我所需要的。我不知道cdecl(和c++decl)程序。谢谢你的提示。cdecl非常好。谢谢你把这件事告诉我,对不起,伙计。起初我有常数,但不知怎的我删除了它。现在它又出现了,我扩展了它以更详细地解释它。谢谢!这是一个很好的解释。我不确定,但您可能应该将const关键字放在按摩处理程序之后。无论如何,这个答案应该更高,typedef是避免混淆的方法@VincentT const
和const T
是相同的(其中T是标识类型的标识符)。你是正确的,<代码> T const 被许多人认为是更一致的。注意很多人认为指针类型DEFS有点模糊;这里不需要在typedef中包含指针,例如typedef void处理程序(void);处理函数func1,func2;Handler*const handlers[]={func1,func2}代码>。这不是声明了一个指向常量函数的指针数组吗?