【发布时间】:2026-02-03 01:05:01
【问题描述】:
我正在尝试为给定的输入构建解析器,有 8 个可能的命令。所以我想,不要像这样使用 case switch 块的丑陋技术:
switch(command)
case cmd1:
.... /*call a function that do cmd1*/
case cmd2
..../*call a function that do cmd2*/
我将在标题中定义一个结构数组,每个结构都包含函数的名称和指向函数的指针:
typedef struct command_info
{
char *name;
void (*func)(int)
};
command_info command_table[] = {{"func1", &func1}, {"func2", &func2} }
这样我可以切换到更优雅的:
int i;
for(i = 0; i < COMMAND_TABLE_LENGTH; i++)
if(!strcmp(command_table[i].name, command))
command_table[i].func(2);
我唯一的问题是,函数有不同的参数(都返回 void)。这对我来说不是问题,因为我可以检查函数是 func1 还是 func2 搜索一个 int 参数,如果是 func3 或 func4 搜索两个(仍然比 @ 更紧凑987654331@)。但是函数指针只指向具有特定类型和数量的参数的函数。如何制作一个可以指向任何函数的通用指针?
【问题讨论】:
-
有一些方法可以在 C 中构建一个通用接口,但它们通常涉及
(void *)指针,并且通常比switch更丑陋。做明智的事情并使用类型安全的参数为每个命令调用单独的函数。无论如何,您可能需要以不同的方式解析这些命令的参数。 -
(但如果你碰巧写了一个brainf*ck解释器,你可以将一个指向公共状态结构的指针传递给所有函数。或者使用
void (*)(void)并在全局状态上操作。) -
标准的相关部分是 C11 §6.3.2.3 Pointers ¶8(第 6.3 节转换的一部分):_指向一种类型的函数的指针可以转换为指向另一种类型的函数的指针,然后再返回;结果应与原始指针比较。如果转换后的指针用于调用类型与引用类型不兼容的函数,则行为未定义。
-
也许没有错,但我的印象是你太努力使你的系统模块化。模块化很好,可以帮助您轻松地维护和扩展您的程序,但它只有在模块底层有一些共同点时才有效。也许解决方案是拥有模块类:二元运算符、一元运算符和函数等。或者也许一元操作是第二个参数为空的二元操作。打印和设置值是模块系统之外的特殊操作。
-
@Some 程序员老兄回复:through generic pointers (i.e. void *)。
void*,一个通用的 object 指针,可能不足以编码一个 function 指针。void*这里没有申请,因为问题是函数指针。
标签: c pointers arguments function-pointers ansi-c