因此,我正在通过POSIX pthreads进入C语言中的多线程,但是我确实在指针的一般概念及其引用和解引用机制方面感到困惑。
中的参数之一
pthread_create(...,pthread_attr_t *attr,...)
是一个函数指针。
此函数通常这样声明:
void *thr_func(void *arg){
thread_data_t *data = (thread_data_t *)arg;
...
}
thr_func是一个函数指针,因此通常我会使用&来引用一个函数指针,例如:
thr_func = &thr_func_impl;
thr_func的参数也是通过*取消引用的指针,以检索它们指向的值。
我不理解的是以下内容:
创建线程时,为什么只在pthread_create(...,thr_func,...)
中给出函数名称而不是地址,以便可以使用它,例如:pthread_create(...,&thr_func,...)
或由{ {1}}已经?
我如何理解这一部分:
pthread_create()
好吧,我想取消引用
类型thread_data的结构通过thread_data_t *data = (thread_data_t *)arg;
称为data。
我不应该这样吗?
thread_data_t *data = ...
->我真的不能跟踪其中发生的事情:
thread_data_t *data;
data = &arg; /* now * on data ,e.g.: *data == struct-data (dereferencing) gives the struct data and data without * just gives the structs start address */
如果有人能很好地解释我会很高兴,谢谢!
答案 0 :(得分:1)
&
运算符传递其地址。即pthread_create(...,thr_func,...)
和pthread_create(...,&thr_func,...)
是可互换的。这与pthreads无关,它是一种语言构造。 arg
是类型void
的指针。为了将其强制转换为类型thread_data_t
的指针,您应该执行(thread_data_t *)arg
。通过使用thread_data_t *data = &arg
,您会将arg
本身的地址归因于data
,而不是地址arg
指向的地址。请考虑以下内容:
int my_int = 7;
void *my_void_ptr = &my_int;
int *my_int_ptr = (int *)my_void_ptr; // Just a cast, points to my_int
printf("%d", *my_int_ptr); // 7
int *my_int_ptr2 = &my_void_ptr; // int pointer to the address of my_void_ptr, issues a warning
printf("%d", *my_int_ptr2 ); // The address of my_void_ptr as an integer
最后,pthreads代表POSIX线程,因此“ POSIX pthreads”是多余的。
答案 1 :(得分:0)
对于第一个问题,函数自然会衰减为指向自身的指针,类似于数组衰减为指向其第一个元素的指针的方式。
所以,如果您有功能
void *thr_fun(void *arg) { ... }
然后,您可以使用&thr_fun
传递指向它的指针,这是显式且(有些人会说)“正确”的方式。另一种方法是使用普通thr_fun
,因为它无论如何都会衰减到&thr_fun
。因此,在C语言中,这实际上是关于样式和个人喜好的问题。
对于第二个问题,请记住void *
是一个通用指针,可以指向任何内容,但没有任何显式类型。因此,您不能取消引用它(因为被取消引用的void *
的类型为void
)。
这就是您需要投射它的原因。
不,您不应该不要获取指针的地址,因为这将为您提供指向指针的指针 。