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

时间:2017-11-29 21:44:44

标签: c parameter-passing void-pointers

例如,在Python中,如果你想将几个东西传递给一个参数,你可以传递一个元组,如:

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

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

论证的类型为void *,这是一个我真的不熟悉的概念。

1 个答案:

答案 0 :(得分:0)

你在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*然后转换为指向不同类型的指针是不行的,但是如果你不小心这样做了,你将不会得到一个很好的例外,如果你'你会崩溃如果不是,那就是幸运和内存损坏或其他难以调试的行为。

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

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

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