如何正确地在C多线程中传递参数给一个线程

4

我正在学习C多线程,发现了一些罕见的事情。

我知道将参数传递给线程必须使用指针。我发现了一个例子,但我不理解它。我会复制相关的行:

pthread_t tid[MAX_THREADS]
int n_veg
pthread_create(&tid[n],NULL,caracter,(void *)n_veg)

“caracter”显然是一个预定义函数。

那么,为什么我们要使用void指针转换而不是int指针转换?有什么相关的区别吗?

其次,为什么我们首先要使用指针转换?我们不能像第一个参数一样使用“&n_veg”吗?

提前感谢您的帮助。

2个回答

10

由于你的两个问题是相关的,我会一起回答它们:pthread_create 接受一个 void * 参数,因此你可以传入任何指针。但在这种情况下,我们实际上没有传递一个指针,而只是将一个简单的整数值作为指针进行转换。这意味着在 caracter 中,你将像这样访问它:

int value = (int)n_veg;

如您所提到的,您可以将实际指针作为 &n_veg 传递并像这样检索值:

int value = *(int *)n_veg;

事实上,在大多数情况下,你需要传递比整数更多的数据,例如结构体,在这种情况下,你 必须 传递一个指针,因为你不能像整数那样直接将其转换为指针。

当你传递指针时,需要记住的一件事是只要线程正在运行,n_veg 就不得超出范围。例如,如果你执行以下操作:

void test() {
  int n_veg;
  pthread_create(&tid[n],NULL,caracter,&n_veg);
}

test返回时,&n_veg将无效,但线程仍可能在运行并且将保持无效地址。因此,通常将传递给线程的结构体动态分配,例如使用malloc,线程可以在完成后使用free释放它。


那么,如果使用整数,传递实际指针或转换值之间是否有真正的区别?还有,为什么要使用 *(int *)n_veg?如果我的第二个问题很愚蠢,请原谅我,这是我在编程方面的第二年,直到本周我才开始使用Java :/ - bluehallu
1
@Hallucynogenyc:是的,有这种方法。如果你传递一个真正的指针,你可以使用指针来改变原始值。关于 *(int *)n_veg:要使用 void *,你需要将其转换为实际类型,因此需要 (int *),然后 * 解引用指针以获取值。 - casablanca

0

pthread_create 的定义如下:

int pthread_create(pthread_t *restrict thread, const pthread_attr_t *restrict attr,
     void *(*start_routine)(void *), void *restrict arg);

因此,它期望其最后一个参数为void *。如果您省略了强制转换,编译器会给出警告。


哦,只是这个方法需要它...我以为空指针对方法是透明操作的。算了。 - bluehallu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接