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转换的时候就又变成了原来的值了,虽然他们其实不是地址,但是被编译器或者程序当作地址来做个转换又何妨!
分享到:
相关推荐
基于C语言泛型指针技术实现泛型顺序栈的应用研究
细细品味C#(泛型专题)细细品味C#(泛型专题)
泛型类、泛型方法、泛型接口、泛型委托 泛型类、泛型方法、泛型接口、泛型委托
泛型集合解释的非常好泛型集合泛型集合泛型集合解释的非常好泛型集合泛型集合泛型集合解释的非常好泛型集合泛型集合泛型集合解释的非常好泛型集合泛型集合
myeclipse小技巧 jsp页面支持泛型
大量使用 递归 以及面向对象形式 支持C语言下复合类型 其中的比较以及遍历 均使用回调方式 留给用户最大空间 另由于C语言不支持泛型 好在还有个void* 无类型指针 合理使用 但比较以及遍历时不知其具体类型 故而采用...
Struts2、Hibernate、Spring整合的泛型DAO (本人评价: 代码开发效率提高30% 代码出错率减少70%) 对于大多数开发人员,系统中的每个 DAO 编写几乎相同的代码到目前为止已经成为一种习惯。虽然所有人都将这种重复...
C#,泛型C#,泛型C#,泛型C#,泛型C#,泛型C#,泛型C#,泛型
C#的泛型C#的泛型
泛型学习和泛型接口和泛型经典示例
【Flutter】Dart 泛型 ( 泛型类 | 泛型方法 | 特定类型约束的泛型 ) https://hanshuliang.blog.csdn.net/article/details/114059611 博客源码快照
泛型和泛型集合类用法泛型和泛型集合类用法泛型和泛型集合类用法泛型和泛型集合类用法泛型和泛型集合类用法
用于在Python 3.4中进行协程驱动的基于异步的泛型编程的小工具库
在.NET FCL为我们提供了很多...结论:如果在C#2.0版本以上,尽量使用泛型集合类,而不使用非泛型集合类。因为,1. 泛型编程是从c#2.0开始才被.net支持的。2.泛型集合在性能和类型安全方面优于非泛型集 合。 。。。。
c#泛型类、泛型方法、泛型接口、泛型委托
运用Java编程,自定义数组大小,解决在数组中加入元素,获取元素;按指定位置删除元素,修改元素;清空数组;数组的排序。
详细讲解了关于c++模板技术中的trait和policy技术,很值得一看。
C++/CLI泛型编程概览 CLI泛型介绍 CLI泛型适用对象 CLI泛型约束 CLI泛型与C++模板 讲座总结 Q&A
泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。 Java语言引入泛型的好处是...
Java泛型编程指南.pdf 此文章译自SUN的泛型编程指南