我基本上想有一个函数列表作为一个函数指针数组;然后我想管理一个索引变量到这个数组中,和一个指针变量,它接受这个数组中的值。考虑下面的C代码来说明这一点,它编译得很好:
#include <stdio.h>
void func_01() {
printf("func_01\n");
}
void func_02() {
printf("func_02\n");
}
void func_03() {
printf("func_02\n");
}
enum func_choice_e {
eFUNC01 = 0,
eFUNC02 = 1,
eFUNC03 = 2,
#define _NUM_FUNC_CHOICE 3
NUM_FUNC_CHOICE = _NUM_FUNC_CHOICE,
};
typedef enum func_choice_e func_choice_t;
void* funcs_ptrs[_NUM_FUNC_CHOICE] = {
&func_01,
&func_02,
&func_03,
};
func_choice_t my_func_choice_idx = eFUNC01;
void* my_func_choice_ptr = &func_01;
int main()
{
my_func_choice_idx = eFUNC02;
my_func_choice_ptr = funcs_ptrs[my_func_choice_idx];
printf("Hello World %p\n", my_func_choice_ptr);
return 0;
}
如上面的代码所示,在代码中,我可以通过索引变量(my_func_choice_ptr = funcs_ptrs[my_func_choice_idx];
)设置指针变量。
然而,我想做一些类似的事情,也是为了初始化-最终,我想先手动初始化数组值和my_func_choice_idx
-然后让指针自动初始化到数组中对应的第my_func_choice_idx
个元素;因此,代替工作指针初始化器:
void* my_func_choice_ptr = &func_01;
我试过这些:
//void* my_func_choice_ptr = funcs_ptrs[my_func_choice_idx]; // error: initializer element is not constant
//void* my_func_choice_ptr = funcs_ptrs[eFUNC01]; // error: initializer element is not constant
//void* my_func_choice_ptr = funcs_ptrs[0]; // error: initializer element is not constant
.正如评论中的错误消息所暗示的那样,这些都不起作用。
我有点明白为什么funcs_ptrs[my_func_choice_idx]
可能会失败-my_func_choice_idx
毕竟是一个变量-但是当编译器到达my_func_choice_ptr = funcs_ptrs[0];
时,它应该已经“知道”funcs_ptrs
的地址,大小和初始值->所以我不明白为什么它不能将my_func_choice_ptr
设置为funcs_ptrs
的第一个条目?!
那么,是否有一些语法可以用于初始化,这将允许我将指针变量 * 初始化 * 为数组中某个条目的给定初始值(类似于在正常代码中工作的赋值my_func_choice_ptr = funcs_ptrs[my_func_choice_idx];
)?
2条答案
按热度按时间eyh26e7m1#
你声明的函数指针是错误的。函数指针不是
void*
,但需要有正确的签名:你可以这样使用它:
如果你想使用
my_func_choice_idx
初始化它,你不能全局地这样做,因为它不是一个常量,但你可以在main
中这样做:hjqgdpho2#
void*
是泛型 object 指针类型,可以在处理指向对象的指针时使用,即:指向变量的指针(或指向其他指针的指针)。void*
与函数指针 * 不 * 兼容。在处理函数指针的最佳实践中,压倒性的强烈建议是 * 始终 * 使用
typedef
。存在两种“学校”/风格:和
我推荐第二种风格,因为它更具可读性,并且使函数指针的使用与对象指针一致。通常,将指针隐藏在typedef后面也是不好的做法。如果我们不把指针隐藏在typedef下,它也会更容易把“常量指针”和“指向常量的指针”分开。
Other things/Misc code review:
void func_01()
是一种老式格式,目前不推荐使用。它通常没有关系 * 除了 * 当处理函数指针时-正确的格式是void func_01(void)
。否则,空括号意味着“函数接受任何参数”,这不是你想要的(特别是C和C++在这里是不同的)。即将到来的C23将最终解决这个问题,但对于旧的/现有的代码库,始终使用显式的(void)
。此外,typedef枚举可以简化,但这是一个风格的评论。同样,枚举标记在大多数时候也不是很有用。
_Static_assert
。__func__
以字符串文字的形式获取函数名。因此,printf("func_01\n");
可以重写为puts(__func__);
,以减少代码重复一点点。%p
实际上并没有为函数指针定义好。如果你想打印他们的地址,最好先转换为uintptr_t
。在修复了以上所有问题之后,代码可能看起来像这样: