我正在尝试从pthread返回值并捕获该值的概念,但我无法理解发生了什么,或者如何使其工作。我有这个创建单个线程的简单程序,这个线程以int值100退出,然后我尝试用pthread_join捕获该值:
#include <stdio.h>
#include <pthread.h>
void *doStuff(void *param) {
int a = 100;
pthread_exit(a);
}
void main() {
pthread_t thread;
int a;
pthread_create(&thread, NULL, doStuff, NULL);
pthread_join(thread, &a);
printf("%d\n", a);
}
它有效,但抛出了一些警告:
./teste.c: In function ‘doStuff’:
./teste.c:7:2: warning: passing argument 1 of ‘pthread_exit’ makes pointer from integer without a cast [enabled by default]
In file included from ./teste.c:2:0:
/usr/include/pthread.h:241:13: note: expected ‘void *’ but argument is of type ‘int’
./teste.c: In function ‘main’:
./teste.c:17:2: warning: passing argument 2 of ‘pthread_join’ from incompatible pointer type [enabled by default]
In file included from ./teste.c:2:0:
/usr/include/pthread.h:249:12: note: expected ‘void **’ but argument is of type ‘int *’
我不明白为什么我会收到这些警告,老实说,我不明白为什么这也有用,因为我认为我必须在pthread_exit上返回一个void指针。
这是一个简单的例子,我正在努力工作,以便我能够完成我正在尝试创建的另一个程序,其中我将有一个线程数组,每个程序都计算一个单浮点值,我想使用pthread_exit和pthread_join将每个计算值存储到浮点数组中,但我真的不知道如何将pthread_join中的值存储到数组中。
答案 0 :(得分:5)
pthread_exit
需要void*
,而非int
。 (请注意,调用pthread_exit(x)
与从线程函数中返回x
相同。)
对您的问题最简单的解决方法是向线程函数传递一个指向int
的指针,用于存储生成的值:
void *doStuff(void *param) {
int a = 100;
*(int*)param = a;
return NULL;
}
int main(void) {
pthread_t thread;
int a;
pthread_create(&thread, NULL, doStuff, &a);
pthread_join(thread, NULL);
printf("%d\n", a);
}
编辑:如果你真的需要使用线程函数的返回值来传达结果,你有几个选择。
(1)将返回值输入和输出void*
:
void *doStuff(void *param) {
int a = 100;
return (void*)a;
}
int main(void) {
pthread_t thread;
pthread_create(&thread, NULL, doStuff, NULL);
void* ptr;
pthread_join(thread, &ptr);
int a = (int)ptr;
printf("%d\n", a);
}
这感觉有点hackish,因为它是。如果您确定从void*
转换为int
将在您将要定位的每个平台上保留void *doStuff(void *param) {
int a = 100;
int* ptr = malloc(sizeof(*ptr));
assert(ptr); /* I'm lazy, sue me. */
*ptr = a;
return ptr;
}
int main(void) {
pthread_t thread;
pthread_create(&thread, NULL, doStuff, NULL);
void* ptr;
pthread_join(thread, &ptr);
int a = *(int*)ptr;
free(ptr);
printf("%d\n", a);
}
的值,那么无论如何都要抛弃。
(2)返回一个指向包含返回值的动态分配存储的指针:
struct foo {
int input1;
int input2;
int result;
};
void *doStuff(void *param) {
foo* f = param;
f->result = f->input1 + f->input2;
return NULL;
}
int main(void) {
foo* ptr = malloc(sizeof(*ptr));
assert(ptr);
ptr->input1 = 5;
ptr->input2 = 3;
pthread_t thread;
pthread_create(&thread, NULL, doStuff, ptr);
pthread_join(thread, NULL);
printf("%d\n", ptr->result);
free(ptr);
}
(3)创建一个结构来封装线程的所有输入/输出参数(重量级,但非常明确):
{{1}}
答案 1 :(得分:0)
只需添加一种方法即可避免所有警告。我实际上通过阅读多个SO答案得到了这个解决方案。
void *thread_fn(void *arg) {
int a = 100;
return (void*)(intptr_t)a;
}
int main(void) {
pthread_t thread;
void* ptr;
int a;
pthread_create(&thread, NULL, thread_fn, &a);
pthread_join(thread, &ptr);
a = (intptr_t)ptr;
printf("%d\n", a);
}
在上面的代码片段中,return (void*)(intptr_t)a;
这里我们首先输入类型转换整数以获得与指针(intptr_t)大小相同的整数类型。然后我们现在可以将它强制转换为void指针。 a = (intptr_t)ptr;