简体   繁体   中英

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

For example, in Python, if you wanted to pass several things into one argument you can just pass a tuple like:

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

I had an idea to pass an array of pointers to the things I want to access in the other function, but they are of different types. Is there a way to make an array of void pointers or something like that?

the argument is of type void* , a concept which I am kind of really unfamiliar with.

You do the same thing as in Python: you pass an argument that's a compound object made of multiple objects. Except that because C is a low-level language, you need to manage several things manually. You need to declare a type for the compound object, you need to ensure that you're using that type consistently, and you need to manage the memory for the compound object. So it's the same conceptual core as in Python, but significantly more difficult in practice.

C has static typing and its type system doesn't have structural aggregate types, so you need to declare a type for the data you're going to pass. Say you want to pass an integer and a character.

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

When you call the thread creation function, you need to create an object of this type and pass a pointer to it.

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

The function that runs the code of the thread takes an argument of type void* . What's void* ? It's a way to do polymorphism in C. A pointer to void is a pointer that doesn't say what it points to. It can't be used directly other than to pass it around, but a pointer to any type can be converted to a pointer to void and vice versa. For example, the 4th argument to pthread_create has the type void* , and above I passed a parameter of type 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);
    …
}

Note that C doesn't carry around type information at runtime. It's ok to convert a pointer to void* and back to the original type. It isn't ok to convert a pointer to void* and then to a pointer to a different type, but if you accidentally do this, you won't get a nice exception, you'll get a crash if you're lucky and memory corruption or other hard-to-debug behavior if you aren't.

In addition, you need to manage the memory used by the parameter object. Above, I showed how to declare a parameter object as a local variable. If you put this in a function, then the object only exists until the function returns. (If param is declared in a block, it's only valid until the block's closing brace.) That's fine if the function waits for the thread to finish accessing the parameter object — above I showed it waiting for the thread to end. But often that's not good enough, so you'll need to allocate memory dynamically.

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

Since the object is allocated dynamically, you'll need to call free on it at some point, presumably in entry_point after it's finished using the object.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM