C:如何安全正确地将多个参数传递给pthread?

考虑这个简单的代码:

void* threadFunction(void* arg) { int argument=(int)arg; printf("%d recieved\n", argument); return NULL; } int main(int argv, char* argc[]) { int error; int i=0; pthread_t thread; int argument_to_thread=0; if ((error=pthread_create(&thread, NULL, threadFunction, (void*)argument_to_thread))!=0) { printf("Can't create thread: [%s]\n", strerror(error)); return 1; } pthread_join(thread, NULL); return 0; } 

这有效,但这里有两件事让我烦恼。
首先,我想向threadFunction()发送多个参数。
当然,我可以传递指向数组的指针,但是如果我想传递两个不同类型的参数呢? (说一个intchar* )怎么做?

在这里困扰我的第二件事是我在编译上面时得到的警告……

 test2.c: In function 'threadFunction': test2.c:8:15: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] int argument=(int)arg; ^ test2.c: In function 'main': test2.c:24:59: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] if ((error=pthread_create(&thread, NULL, threadFunction, (void*)argument_to_thread))!=0) { ^ 

现在,我可以通过这样做来消除这种情况:

 if ((error=pthread_create(&thread, NULL, threadFunction, (void*)&argument_to_thread))!=0) { printf("Can't create thread: [%s]\n", strerror(error)); return 1; } 

但是,让我说我不想通过引用传递它…有没有方法传递,说…一个int,值作为参数而没有编译器警告我?

有两种方法可以做到这一点:

  1. 使用malloc获取参数结构的存储空间,并让新线程负责在参数完成后free调用。 (注意:如果pthread_create失败,则需要在故障路径中free此存储空间。)

  2. 使用信号量(或其他同步,但信号量是目前最轻的)。

以下是后者的一个例子:

 struct args { int a; char *b; sem_t sem; }; void *thread_func(void *p) { struct args *args = p; int a = args->a; char *b = args->b; sem_post(args->sem); ... } /* in caller */ struct args args; args.a = ...; args.b = ...; sem_init(&args.sem, 0, 0); pthread_create(&tid, 0, thread_func, &args); sem_wait(&args.sem); ... 

如果你想通过值传递,但让警告消失,请使用此强制转换:

 (void *)(uintptr_t)argument_to_thread 

通过uintptr_t的中间uintptr_t避免了大小不匹配。 同样,在回退时,使用:

 (int)(uintptr_t)voidptr_arg 

如评论中所述,不一定建议采用上述方法,因为它依赖于实现定义的行为。 一个完全可移植的方法,假设您不需要全范围的int但只需要很小的范围,是:

 static const char int_to_ptr_trick[MAXVAL]; void *ptr = int_to_ptr_trick + int_val; int int_val = (char *)ptr - int_to_ptr_trick; 

传递整数的地址。

 int argument = 123 ; pthread_create(&thread, NULL, threadFunction, &argument)) ; 

并在线程函数中

  int argument= *(int*)arg ; 

如果您希望传递多个参数,则可以使用与上述示例相同的方法创建包含值的结构。

如果函数的参数为​​void *,则不能按值传递整数。 您必须提供变量或结构的地址。