首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在C中声明常量函数指针数组?

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

Stack Overflow用户
提问于 2008-12-03 15:11:26
回答 5查看 29.3K关注 0票数 25

我需要像这样声明一个指向函数的指针数组:

代码语言:javascript
运行
复制
extern void function1(void);
extern void function2(void);
...

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

但是,我希望数组声明为常量--既包括数组中的数据,也包括指向数据的指针。不幸的是,我不记得把const关键字放在哪里了。

我假设实际的指针,在本例中是MESSAGE_HANDLERS,已经是常量了,因为它被声明为数组。另一方面,如果数组中的函数指针被声明为如下所示,那么在运行时不能更改它吗?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2008-12-03 16:26:53

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

如何在没有帮助的情况下声明这些东西?

数组

代码语言:javascript
运行
复制
T t[5];

是一个由5个T组成的数组。要使T成为函数类型,您可以将返回类型写在左边,将参数写在右边:

代码语言:javascript
运行
复制
void t[5](void);

是一个由5个函数组成的数组,返回,不带参数。但是函数本身不能填充在数组中!它们不是对象。只有指向它们的指针才能。

关于

代码语言:javascript
运行
复制
void * t[5](void);

这仍然是错误的,因为它只是将返回类型更改为void的指针。您必须使用括号:

代码语言:javascript
运行
复制
void (*t[5])(void);

这将会真正起作用。T是一个由5个指针组成的数组,指向返回void且不带参数的函数。

太棒了!那么指向arras的指针数组呢?这是非常相似的。元素类型显示在左侧,尺寸显示在右侧。同样,需要使用括号,因为否则数组将变成整数指针的多维数组:

代码语言:javascript
运行
复制
int (*t[5])[3];

就这样!一个由5个指针组成的数组,指向3个整型数组。

那么函数呢?

我们刚刚学到的关于函数的知识也是正确的。让我们声明一个函数,它接受一个int,返回一个指向另一个函数的指针,不带参数,返回void:

代码语言:javascript
运行
复制
void (*f(int))(void);

出于与上面相同的原因,我们需要再次使用括号。我们现在可以调用它,并再次调用指向的返回函数。

代码语言:javascript
运行
复制
f(10)();

返回函数的指针返回另一个函数的指针

那这个呢?

代码语言:javascript
运行
复制
f(10)(true)(3.4);

?换句话说,一个接受int的函数,返回一个指向一个接受bool的函数的指针,返回一个接受double的函数的指针,并返回void,会是什么样子?答案是你只要嵌套它们就行了:

代码语言:javascript
运行
复制
void (*(*f(int))(bool))(double);

你可以这样做无数次。实际上,您也可以返回指向数组的指针,就像返回指向函数的指针一样:

代码语言:javascript
运行
复制
int (*(*f(int))(bool))[3];

这是一个采用int的函数,返回指向一个采用bool的函数的指针,返回一个指向3个int的数组的指针

这和const有什么关系?

既然上面解释了如何从基本类型构建复杂类型,您可以将const放在您现在知道它们所属位置的地方。试想一下:

代码语言:javascript
运行
复制
T c * c * c ... * c name;

T是我们最后指向的基本类型。c代表const或not const。例如

代码语言:javascript
运行
复制
int const * const * name;

将声明name使类型指针指向指向常量int的常量指针。您可以更改name,但不能更改*name,其类型为

代码语言:javascript
运行
复制
int const * const

也不是**name,它的类型是

代码语言:javascript
运行
复制
int const

让我们将其应用于上面的函数指针:

代码语言:javascript
运行
复制
void (* const t[5])(void);

这实际上会声明数组包含常量指针。因此,在创建(和初始化)数组之后,指针是const,因为const出现在星号之后。请注意,在这种情况下,我们不能将const放在星号之前,因为没有指向常量函数的指针。函数不能是const,因为这是没有意义的。因此,以下内容无效:

代码语言:javascript
运行
复制
void (const * t[5])(void);

结论

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

票数 59
EN

Stack Overflow用户

发布于 2008-12-03 15:23:01

在这样的情况下,做一个typedef来命名你的函数签名,这使得它变得简单得多:

代码语言:javascript
运行
复制
typedef void MESSAGE_HANDLER(void);

有了这一点,它应该是:

代码语言:javascript
运行
复制
MESSAGE_HANDLER * const handlers[] = { function1, function2 };

来获取数组常量的实际内容。

编辑:从typedef中删除了指针部分,这真的更好(在线学习)。

票数 16
EN

Stack Overflow用户

发布于 2008-12-03 15:25:11

cdecl说:

代码语言:javascript
运行
复制
cdecl> explain void (* const foo[])(void)
declare foo as array of const pointer to function (void) returning void

这是你需要的吗?

票数 15
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/337449

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档