【问题标题】:pthreads_create(...) executed function - pointer confusionpthreads_create(...) 执行的函数 - 指针混淆
【发布时间】:2018-07-11 08:33:41
【问题描述】:

所以我正在通过 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,...) 或者这是由pthread_create() 完成的?

  • 我必须如何理解这部分: thread_data_t *data = (thread_data_t *)arg; 好的,我想取消引用 thread_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 */

-> 我无法真正了解里面发生的事情:

void *thr_func(void *arg){ thread_data_t *data = (thread_data_t *)arg; ... }

如果有人有好的解释,我会很高兴,谢谢!

【问题讨论】:

    标签: c multithreading pointers pthreads function-pointers


    【解决方案1】:
    1. 将函数名作为参数传递等同于使用& 运算符传递其地址。 IE。 pthread_create(...,thr_func,...)pthread_create(...,&thr_func,...) 可以互换。这与 pthread 无关,它是一种语言结构。
    2. argvoid 类型的指针。为了将其转换为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”是多余的。

    【讨论】:

    • 好的,我想我明白了。我不知道函数名和应用于它的地址运算符是可以互换的,但这是有道理的,因为我们唯一感兴趣的可能是函数在程序地址空间中的起始位置。在您的解释中void *my_void_ptr = &my_int 只是声明了一个指向 my_int 的 void 指针。
    • [@Leo 之前评论的继续:] 由于该指针尚未被分配类型,我们需要使用:...= (int *) my_void_ptr; 对其进行强制转换并将其分配给 f.e. int *my__int_ptr = (int *) my_void_ptr; 以便在函数中使用它,它现在也只是一个指针,指向与my_void_ptr 相同的地址。现在已经将my_int_ptr 声明为指针,请参见:int *my_int_ptr =...;,我们可以简单地取消引用并通过....*my_int_ptr; 获取其值,并通过@987654341 获取存储值的地址(在您的示例中为my_int/7) @.
    【解决方案2】:

    对于第一个问题,函数自然会衰减为指向自身的指针,类似于数组衰减为指向其第一个元素的指针的方式。

    所以如果你有一个函数

    void *thr_fun(void *arg) { ... }
    

    然后您可以使用&thr_fun 将指针传递给它,这是明确且(有人会说)“正确”的方式。另一种是使用普通的thr_fun,因为无论如何它都会衰减到&thr_fun。所以在 C 中,这确实是一个关于风格和个人偏好的问题。


    对于第二个问题,请记住 void * 是一个通用指针,它可以指向任何东西,但它没有任何显式类型。因此,您不能取消引用它(因为取消引用的 void * 将具有 void 类型)。

    这就是你需要投射它的原因。

    你不应该获取指针的地址,因为这会给你一个指针指向指针

    【讨论】:

    • 为了反驳“正确”的方式,我想说最好的方式是使用语言允许的最短结构,但仍然是正确的。
    猜你喜欢
    • 1970-01-01
    • 2017-07-25
    • 1970-01-01
    • 1970-01-01
    • 2010-09-25
    • 2011-09-04
    • 2016-11-08
    • 2020-10-07
    相关资源
    最近更新 更多