将多个参数传递到一个 void 指针参数的好方法? (C)

A good way to pass several arguments into one void pointer argument? (C)

例如,在 Python 中,如果您想将多个内容传递到一个参数中,您可以只传递一个元组,例如:

thread_create(v, w, x, (y, z))

我有一个想法,将一个指针数组传递给我想在另一个函数中访问的东西,但它们的类型不同。有没有办法制作一个空指针数组或类似的东西?

参数是 void* 类型,我对这个概念有点陌生。

您做的事情与 Python 相同:您传递一个参数,该参数是由多个对象组成的复合对象。除了因为 C 是一种低级语言,你需要手动管理几件事。您需要为复合对象声明一个类型,您需要确保您一致地使用该类型,并且您需要管理复合对象的内存。所以它与 Python 中的概念核心相同,但在实践中要困难得多。

C 有静态类型,它的类型系统没有结构聚合类型,所以你需要为你要传递的数据声明一个类型。假设您想传递一个整数和一个字符。

typedef struct {
    int y;
    char *z;
} thread_param_t;

调用线程创建函数时,需要创建一个该类型的对象,并传递一个指针给它。

thread_param_t param = {42, "hello"};
pthread_create(thread, attr, entry_point, &param);
…
pthread_join(thread, NULL);

运行线程代码的函数采用void*类型的参数。 void* 是什么?这是在 C 中实现多态性的一种方式。指向 void 的指针是一个没有说明它指向什么的指针。除了传递它之外不能直接使用它,但是指向任何类型的指针都可以转换为指向 void 的指针,反之亦然。例如,pthread_create 的第 4 个参数的类型为 void*,上面我传递了一个类型为 thread_param_t* 的参数。

void* entry_point(void *param_arg) {
    thread_param_t *param = param_arg;
    printf("entry_point called with y=%d and z=%s\n", param->y, param->z);
    …
}

请注意,C 在运行时不携带类型信息。可以将指向 void* 的指针转换回原始类型。将指针转换为 void* 然后转换为指向不同类型的指针是不对的,但如果你不小心这样做,你不会得到一个很好的异常,如果你会崩溃幸运的是内存损坏或其他难以调试的行为,如果不是的话。

此外,您还需要管理参数对象使用的内存。上面,我展示了如何将参数对象声明为局部变量。如果你把它放在一个函数中,那么这个对象只存在到函数 returns 之前。 (如果 param 在块中声明,它仅在块的右大括号之前有效。)如果函数等待线程完成对参数对象的访问就没问题了——上面我展示了它等待线程结束。但通常这还不够好,因此您需要动态分配内存。

thread_param_t *param;
param = malloc(sizeof(*param));
if (param == NULL) …;
pthread_create(thread, attr, entry_point, &param);

由于对象是动态分配的,您需要在某个时候对其调用 free,大概是在 entry_point 使用完对象后。