这是 void 指针的正确使用吗?

发布于 2024-10-31 19:34:40 字数 514 浏览 5 评论 0原文

这个问题是关于在特定实现中使用 void 指针的适当性。

我有一个相对简单的程序,由无限循环组成。在每个循环中,程序都会迭代固定范围的常量值,并对每个值调用一个函数。被调用的特定函数可以是三个可用函数之一,并在运行时由参数指定。在无限循环开始之前,有一个条件块,它根据提供的参数设置指向函数的函数指针。这样,条件逻辑只需运行一次,而不是在每个循环的每次迭代中运行。

我已经实现了并且效果很好,但我想在每次调用函数之间保持状态。我的建议是将状态存储在结构中,并在对每个值调用函数时传递该结构。问题在于每个函数需要不同的结构来存储其状态的不同值集,并且所有三个函数的原型必须兼容(对于函数指针)。我打算通过在三个函数的原型中使用 void 指针来解决这个问题,从而保持兼容的原型,但允许我向每个函数传递不同的结构。

问题是;我的建议是否适当使用了 void 指针,或者它是否引入了太多的运行时动态,因此我应该重新考虑我的方法?

注意:不可能在三个函数中的每一个中使用静态变量,因为结构也需要在无限循环中可用,因为在迭代值范围之前和之后还需要进行一些处理。

This question is about the appropriateness of using void pointers in a particular implementation.

I have a relatively simple program that consists of an infinite loop. On each loop, the program iterates over a fixed range of constant values and calls a function on each value. The particular function which is called can be one of three available and is specified at run time by an argument. Before the infinite loop starts, there is a condition block which sets a functional pointer to a function based on the supplied argument. This way the condition logic only has to be run once and not on every iteration in every loop.

This I have implemented and it works well, but I want to keep state between each call to the function. My proposal is to store state in a struct and pass that struct when calling the function on each of the values. The problem is that each function requires a different struct to store a different set of values of its state and the prototype of all three functions must be compatible (for the function pointer). I intend to solve this by using a void pointer in the prototypes of the three functions, thus maintaining compatible prototypes but allowing me to pass a different struct to each function.

The question is; is my proposal an appropriate use of void pointers or is it introducing too much runtime dynamism and I should therefore rethink my approach?

Note: It is not possible to use static variables in each of the three functions as the structs also need to be available in the infinite loop as there is also some processing to be done before and after the range of values is iterated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

痴情换悲伤 2024-11-07 19:34:40

只要您小心地保持调用类型正确,这就是完成您所描述的内容的一种相当 C 语言惯用的方法。

As long as you are careful to keep your calls type-correct, this is a fairly C-idiomatic way to accomplish what you describe.

冬天的雪花 2024-11-07 19:34:40

您可以通过使用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* 指针。

You could gain some measure of type safety by using a 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 *);

Then all your functions could be of type daemon_function but take different arguments through ocd.s1 or ocd2.s2. I'd tend to call all that a bunch of pointless busy-work though. A simple void* would work just as well.

You could also include a magic number at the front of your structures and then the functions could check type safety by looking at the magic number and seeing if it was the right one:

#define MAGIC 0x4d475600L
typedef struct {
    long magic;
    /* ... */
} whatever;

And then:

int f(void *p) {
    whatever *w = (whatever *)p;
    if(w->magic != MAGIC) {
        /* complain and go boom! */
    }
    /* ... */
}

I did the magic number trick all the time back in my Motif programming days, you pass around a lot of void* pointers in Motif/Xt/X11 development.

才能让你更想念 2024-11-07 19:34:40

空指针是一种告诉 c 类型系统您希望它停止执行其工作并相信您不会搞砸的方法。这是 void * 的正确使用,唯一的问题是您无法访问编译器执行的任何类型检查。您可能会创建一些非常奇怪且难以诊断的错误。如果您确定自己知道自己在做什么(听起来就像您所做的那样),并且多次检查了代码的每一行并确定其中没有逻辑错误,那么应该没问题。

Void pointers are a method to tell the c typing system that you want it to stop doing its job and trust you to not mess up. It is an appropriate use of a void *, the only issue is that you have lost access to any type checking that your compiler performs. You can potentially create some very bizarre and hard to diagnose bugs. If you are sure that you know what you are doing (you sound like you do) and if you have checked every single line of your code several times and are sure that there are no logical errors in it, then you should be fine.

老娘不死你永远是小三 2024-11-07 19:34:40

void * 在 C 语言中非常惯用。我个人普遍使用它,但每当我这样做时,为了安全起见,我倾向于使用标记结构,即我在每个结构的开头放置一个唯一的类型 ID识别它。

void * is quite idiomatic in C. Personally I use it prevalently, but whenever I do it, I tend to used tagged structures for safety, i.e. I put a unique type ID at the beginning of each structure to identify it.

橘和柠 2024-11-07 19:34:40

一般来说是可以的。
我真的更喜欢使用 void * 上下文,但看起来你想避免它。
由于您已经有一些解析参数并选择函数的代码,因此您只需在 switch 中选择函数并为每次迭代显式调用它即可。

Generally it is OK.
I really prefer using the void * contexts but it looks like you want to avoid it.
Since you already have some code that parses the argument and choose the function, you can just select the function in a switch and call it explicitly for each iteration.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文