如何在C中声明一个常量函数指针数组?

我需要声明一个指向函数的指针数组,如下所示:

extern void function1(void); extern void function2(void); ... void (*MESSAGE_HANDLERS[])(void) = { function1, function2, ... }; 

但是,我希望将数组声明为常量 – 数组中的数据和指向数据的指针。 不幸的是,我不记得在哪里放置const关键字。

我假设在这种情况下,实际指针MESSAGE_HANDLERS已经是常量,因为它被声明为数组。 另一方面,如果声明如图所示,那么数组中的函数指针是否可以在运行时更改?

有一种技术可以记住如何构建这种类型。 首先尝试从名称开始读取指针并从右向左阅读。

如何在没有帮助的情况下申报这些内容?

数组

 T t[5]; 

是一个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个指针数组

function怎么样?

我们刚刚学到的function也是如此。 让我们声明一个带有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]; 

这是一个函数,它返回一个指向函数的指针,该函数使bool返回一个指向3 int数组的指针

与const有什么关系?

既然上面已经解释了如何从基本类型构建复杂类型,那么可以将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 ,因为没有指向常量函数的指针 。 函数根本不能是const,因为没有意义。 所以以下内容无效:

 void (const * t[5])(void); 

结论

实际上,C ++和C声明函数和数组的方式实际上有点令人困惑。 你必须首先考虑它,但如果你理解它,你可以使用它编写非常紧凑的函数声明。

cdecl说:

 cdecl> explain void (* const foo[])(void) declare foo as array of const pointer to function (void) returning void 

这是你需要的吗?

在这种情况下,使用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; } 

我不确定这是否适用于’C’。 它确实在’C ++’中工作:

  • 首先将MESSAGE_HANDLERS定义为类型:

    typedef void (*MESSAGE_HANDLER)();

  • 然后,使用类型定义将数组声明为常量:

    MESSAGE_HANDLER const handlers[] = {function1, function2};

诀窍在于typedef ,如果你可以在’C’语义上做同样的事情,它也应该工作。