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++那样的模板机制,但是通过巧妙地使用`void *`指针和函数指针,开发者仍然能够在一定程度上实现泛型编程的效果。这种方式不仅增加了代码的灵活性,也提高了代码的复用性,使得开发者能够在...
虽然C语言本身并不直接支持泛型,但通过一些技巧,如使用无类型指针`void*`和辅助函数,可以模拟泛型编程的效果。 1. **无类型指针**: 在C语言中,`void*`指针可以存储任何类型的数据的地址,是实现泛型编程的...
5. **类型检查和转换**:虽然C语言不支持泛型,但我们可以使用`void*`进行类型转换,并在运行时进行类型检查,以确保数据操作的正确性。 例如,如果我们想为整型数据创建一个链式栈,可以这样做: ```c // 定义整型...
- **应用场景**:`void*`指针在泛型编程中十分有用,尤其是在实现多态性或通用函数时。 #### C/C++语言可变参数表深层探索 - **可变参数列表**:在C/C++中,函数可以接受数量不定的参数,通过`va_list`、`va_start...
- **泛型设计**:除了整数,顺序栈还可以用于存储其他类型的数据,通过模板类实现泛型编程。 - **错误处理**:在实际应用中,应添加适当的错误检查,如弹栈时栈为空、压栈时栈已满等情况。 5. **应用场景** 顺序...
- **定义**: C++是一种静态类型的、编译式的、通用的、大小写敏感的、不规则的编程语言,支持过程化编程、面向对象编程和泛型编程。 - **发展历程**: C++由Bjarne Stroustrup于1979年在贝尔实验室开始设计和实现,...
了解内存的分配和释放,防止内存泄漏和悬空指针是编程中的重要技巧。 4. **类与对象**:C++支持面向对象编程,类是对象的蓝图,对象则是类的实例。掌握构造函数、析构函数、成员函数、封装、继承、多态等概念,能够...
- **掌握沟通技巧**:良好的沟通能力不仅可以帮助你更好地表达自己,还能帮助你在团队协作中发挥更大的作用。 - **模拟面试**:参加模拟面试可以帮助你适应真实的面试环境,提高临场应变能力。 以上解析涵盖了华为...
### .Net的一些技巧与C#知识点详解 #### 1. 说说.NET框架与结构? - **结构**:在.NET框架中,结构是一种值类型的数据结构,它存储在栈上而不是堆上。当一个结构被赋值时,实际上复制的是整个结构的值,这意味着...
通过学习和分析这些小程序,可以更深入地理解C++语言的工作原理和编程技巧。实践是掌握编程技能的最佳途径,所以尝试编译和运行这些程序,查看它们如何实现上述知识点,将有助于提升你的C++编程能力。
《Think in C++ Volume 2》是一本专注于教授高级 C++ 编程技巧和技术的书籍,它作为第二卷,延续了第一卷的基础概念,并深入探讨了更复杂的主题。本书适合已经掌握了 C++ 基础知识并希望进一步提高编程技能的读者。 ...
20. **利用泛型(Generic)提高代码复用**:泛型允许创建类型参数化的类、接口和方法,提高代码的灵活性和效率。 21. **理解并使用委托和事件的弱引用**:弱引用防止委托引用阻止对象被垃圾回收,适用于长时间存在...
在大学的C++基础课程中,初学者会接触到一系列的核心概念和编程技巧。"C++基础大学教程例题"这个主题旨在帮助初学者通过实际的编程例子深入理解C++语言。下面将详细介绍C++的基础知识,并结合可能在教程中出现的例题...
Objective-C是一门强大的...总的来说,Objective-C的这些小技巧和概念构成了其强大的面向对象编程基础,使得开发者能够构建出灵活、可维护的软件系统。理解和掌握这些技巧对于编写高质量的Objective-C代码至关重要。
本篇文章将深入探讨如何在C#中使用数组作为函数参数,这是一项常见的编程技巧,尤其对于处理批量数据时非常有用。我们将通过实例来阐述这一概念。 首先,了解数组的基本概念是必要的。在C#中,数组可以是一维、二维...
- 探讨C#中的高级编程技术,如泛型、委托、事件、异步编程等。 - **WinForm控件的高级使用:** - 进一步探索WinForm控件的高级特性和用法。 - **第六讲、C#的高级编程技术、异常、代表、系统环境信息(二)** -...
- 使用`void*`指针可以存储任意类型的指针。 - 在进行类型转换时需要特别小心,以防止类型不匹配的问题。 #### 46. 函数指针 - 函数指针可以作为函数的参数或返回值。 - 使用函数指针可以实现回调等功能。 #### 47...