`
hankgong
  • 浏览: 196122 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

void* 泛型指针一点小技巧

阅读更多

void *有人把它叫为generic pointer,中文翻译为泛型指针。一般来说,它的用法应该是作为指针来用,比如下面的例子

 

int main()
{
  int i;
  char c;
  void *the_data;

  i = 6;
  c = 'a';

  the_data = &i;
  printf("the_data points to the integer value %d\n", *(int*) the_data);

  the_data = &c;
  printf("the_data now points to the character %c\n", *(char*) the_data);

  return 0;
}

 

 这里the_data就是作为一个可以任意指向的多功能指针来用的,但是下面的例子里面

 

#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);
}

 

 在上面的pthread传递参数的时候,t或者threadid明明就不是指针,这里为什么也用void*。pthread_create函数里面的定义就规定必须传递void*的参数,这是我们是不能选的,如果按照一定要是指针的思维,程序应该是下面的才对

 

#include <iostream>
#include <pthread.h>
//#include <stdio.h>
#include <stdlib.h>

#define NUM_THREADS 5

using namespace std;

void *PrintHello(void *threadid) {
    long tid;
    cout<<"Checking generic pointer"<<threadid<<endl;
    tid = *(long*)threadid;
    cout<<"Hello world! It's me, thread #"<< tid <<endl;
    pthread_exit(NULL);
}

int main()
{
    pthread_t threads[NUM_THREADS];
    int rc;
    long t;

    for(t=0; t<NUM_THREADS; t++){
        cout<<"In main: creating thread"<<t<<endl;

        rc = pthread_create(&threads[t], NULL, PrintHello, (void *)&t);



        if(rc){
            cout<<"ERROR; return code from  pthread_create() is"<<rc<<endl;
            exit(-1);
        }


    }

    pthread_exit(NULL);
    //cout << "Hello World!" << endl;
    return 0;
}

 

 可以这样的话,你会发现在PrintHello里面打印的threadid是错误的,是什么原因呢?

 

 

 

 

 

 

解答:

如果用上面的方式,传递的就是t的地址给threadid,那么PrintHello的时候,主程序里面的t的修改是另外一个线程,所以不能保证PrintHello打印的这个地址的数没有被主程序修改过。

 

那么怎么传递才对?我们上面的倒数第二个其实是对的,这个时候t的值其实是作为地址传递给threadid,然后用long转换的时候就又变成了原来的值了,虽然他们其实不是地址,但是被编译器或者程序当作地址来做个转换又何妨!

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics