【问题标题】:pthread_create argument in c multi thread programmingc多线程编程中的pthread_create参数
【发布时间】:2013-07-18 00:50:00
【问题描述】:

pthread_create(&Thread,NULL,ChildThread,(void *)100);

1) 我们可以像上图那样传递 pthread_create 的第四个参数吗?不应该是指针变量吗?

【问题讨论】:

  • 但是你把它屏蔽成一个 void *,它会运行正常。
  • 它是如何工作的?我们不能将数字转换为指针吗?
  • 您可以将数字转换为指针,但是当您尝试将其恢复为数字时,您的状态会很糟糕,具体取决于架构,您可能会遇到问题。
  • C 允许您在指针和整数之间进行转换,只要指针值可以由整数类型保存。但是,结果是实现定义的。如果指针值大于整数类型可以容纳的值,则结果未定义。
  • @user1762571 - 您可以将任何整数转换为 void*,但反之则很危险,将 void* 转换为 int 是不可移植的。在 64 位架构上,指针为 64 位宽,但 int 仅为 32 位。 Any pointer type may be converted to an integer type. Except as previously specified, the result is implementation-defined. If the result cannot be represented in the integer type, the behavior is undefined. The result need not be in the range of values of any integer type.

标签: c pthreads


【解决方案1】:

只是一个例子(not meant to be correct way of doing it; but to serve as example code for anyone who want to play with it):

#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <pthread.h>

void *print_number(void *number) {
    printf("Thread received parameter with value: %d\n", number);
    return (void *)number;
}

int main(int argc, char *argv[]) {
    pthread_t thread;
    void *ret;
    int pt_stat;
    pt_stat = pthread_create(&thread, NULL, print_number, (void *)100);
    if (pt_stat) {
        printf("Error creating thread\n");
        exit(0);
    }

    pthread_join(thread, &ret);
    printf("Return value: %d\n", ret);

    pthread_exit(NULL);

    return 0;
}

如果指针值大于 int 可以容纳的值,这将导致未定义的行为。请参阅 C99 中的这句话:

Any pointer type may be converted to an integer type. Except as previously specified, the result is implementation-defined. If the result cannot be represented in the integer type, the behavior is undefined. The result need not be in the range of values of any integer type.

【讨论】:

  • @xaxxon - 是的,这是错误的,会导致未定义的行为;我同时在您的下方对 OP 的帖子添加了评论。我只是将其添加为其他有兴趣使用它的示例代码。 :) 抱歉应该在答案中提到这一点。
【解决方案2】:

(void *)100 的意思是取整数值 100 并将其视为指向某些未指定类型的内存(即(void *))的指针。在这种情况下,这意味着将整数值 100 压入堆栈作为pthread_create 的参数。据推测,ChildThread 将传递给它的void * 转换回int,然后将其用作数字。

从根本上说,指针实际上只是内存地址。内存地址只是描述内存位置的数字,因此将int 转换为任何类型的指针都是合法的。在某些情况下,将int 转换为指针绝对是正确的做法和必需的,但是,它们往往很少见。例如,如果您正在为嵌入式控制器编写代码,并且想要为内存映射 I/O 设备编写驱动程序,那么您可以将设备的基地址转换为指向 int 或 struct 的指针,然后通过正常的 C 访问访问设备的指针。将ints 转换为指针的另一个示例是实现低级虚拟内存管理例程以分配操作系统的物理内存。

假设指针的大小至少足以容纳您尝试传递的整数,您提供的代码并不少见并且可以工作。大多数实现pthread_create 的系统可能会有一个 32 位或 64 位指针,因此您的示例很可能有效。恕我直言,这有点滥用,因为在这种情况下 100 可能不指代内存位置,并且 C 不保证 void * 大到足以容纳 int

【讨论】:

    【解决方案3】:

    取自 POSIX Thread Progreamming 上的一篇优秀文章。任何新手都必须阅读。

    Example Code - Pthread Creation and Termination
    
    #include <pthread.h>
    #include <stdio.h>
    #define NUM_THREADS     5
    
    void *PrintHello(void *threadid)
    {
       long tid;
       tid = (long)threadid;
       printf("Hello World! It's me, thread #%ld!\n", tid);
       pthread_exit(NULL);
    }
    
    int main (int argc, char *argv[])
    {
       pthread_t threads[NUM_THREADS];
       int rc;
       long t;
       for(t=0; t<NUM_THREADS; t++){
          printf("In main: creating thread %ld\n", t);
          rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
          if (rc){
             printf("ERROR; return code from pthread_create() is %d\n", rc);
             exit(-1);
          }
       }
    
       /* Last thing that main() should do */
       pthread_exit(NULL);
    }
    

    解释:

    您可以将 100 作为第四个参数传递给 pthread_create() 。在函数 PrintHello 中,您可以将 void* 类型转换回正确的类型。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-07-11
      • 2013-04-20
      • 1970-01-01
      • 1970-01-01
      • 2020-12-11
      • 1970-01-01
      • 2015-03-28
      • 1970-01-01
      相关资源
      最近更新 更多