这个问题是关于在特定实现中使用void指针的适当性。
我有一个相对简单的程序,它包含一个无限循环。在每个循环中,程序迭代固定范围的常量值并在每个值上调用一个函数。调用的特定函数可以是三个中的一个,并且在运行时由参数指定。在无限循环开始之前,有一个条件块,它根据提供的参数设置一个函数指针。这样,条件逻辑只需要运行一次,而不是每次循环中的每次迭代。
我已经实现了它并且运行良好,但是我希望在每次调用函数之间保持状态。我的建议是将状态存储在结构中,并在每个值上调用函数时传递该结构。问题是每个函数都需要一个不同的结构来存储其状态的不同值集,并且所有三个函数的原型必须兼容(对于函数指针)。我打算通过在三个函数的原型中使用void指针来解决这个问题,从而保持兼容的原型,但允许我将不同的结构传递给每个函数。
问题是;我的建议是否适当使用了void指针,或者它是否引入了太多的运行时动态,因此我应该重新考虑我的方法?
注意:不可能在三个函数中的每个函数中使用静态变量,因为结构也需要在无限循环中可用,因为在迭代值范围之前和之后还要进行一些处理。
答案 0 :(得分:5)
只要你小心保持你的电话类型正确,这是完成你所描述的相当C语言的方法。
答案 1 :(得分:2)
您可以使用union
:
typedef struct {
int a;
char *b;
} s1;
typedef struct {
double d;
int *e;
} s2;
typedef union {
s1 s1;
s2 s2;
} ocd;
typedef int (*daemon_function)(ocd *);
然后,您的所有功能都可以是daemon_function
类型,但可以通过ocd.s1
或ocd2.s2
采用不同的参数。我倾向于称之为一堆毫无意义的繁忙工作。一个简单的void*
也可以正常工作。
您还可以在结构的前面加上一个幻数,然后功能可以通过查看幻数来检查类型安全性,看看它是否正确:
#define MAGIC 0x4d475600L
typedef struct {
long magic;
/* ... */
} whatever;
然后:
int f(void *p) {
whatever *w = (whatever *)p;
if(w->magic != MAGIC) {
/* complain and go boom! */
}
/* ... */
}
我在Motif编程时代一直做着神奇的数字技巧,你在Motif / Xt / X11开发中传递了很多void*
指针。
答案 2 :(得分:1)
void *
在C语言中非常惯用。我个人经常使用它,但每当我这样做时,我倾向于使用标记结构来保证安全,即我在每个结构的开头放置一个唯一的类型ID来识别它
答案 3 :(得分:1)
Void指针是一种告诉c类型系统你想让它停止工作并相信你不要搞砸的方法。它是void *的适当用法,唯一的问题是您无法访问编译器执行的任何类型检查。您可以创建一些非常奇怪且难以诊断的错误。如果你确定你知道自己在做什么(听起来像你那样),并且如果你已经多次检查过代码的每一行,并且确定它没有逻辑错误,那么你应该没问题。 / p>
答案 4 :(得分:0)
一般来说没关系。
我真的更喜欢使用void *
上下文,但看起来你想要避免使用它。
由于您已经有一些解析参数并选择函数的代码,您只需在开关中选择函数并为每次迭代显式调用它。