对线程等待函数pthread_join二级指针参数分析
分析之前先搞明白,这个二级指针其实在函数内部是承接了上个线程的返回值。
看man手册,发现返回值是个普通指针。人家用二级指针来承接,可能准备干大事。这个可以自己搜索一下。原因嘛,二级指针是保存了这个地址。一级指针承接的话就是这个地址。
那既然二级指针保存了,我们如何访问那?开始我觉得直接来个二级指针,然后*访问算了,但是下面的东西。让你不能那么干了!其实非要那样也可以 malloc呗!
线程创建函数pthread_create的函数原型如下:
int pthread_create(pthread_t *restrict thread,
const pthread_attr_t *restrict attr,
void *(*start_routine)(void*), void *restrict arg);
其中,thread是要创建的线程;
attr指定线程的属性,缺省值为NULL;
start_routine是线程要执行的函数;
arg是传递给线程执行的函数的参数;
要注意的是:start_routine是函数指针
线程等待函数pthread_create的函数原型如下:
int pthread_join(pthread_t thread, void **value_ptr);
其中,thread是要等待的线程名;
value_ptr:指针*value_ptr指向线程返回的参数
在使用时要注意的是:针对value_ptr,应该先声明一个一级指针,然后通过取地址的方式传给pthread_create函数,而不应该直接定义一个二级指针,将这个二级指针直接传递给pthread_create。
如:
正确的传递方法:
void *ret;
pthread_join(thread, &ret);
错误的传递方法:
void **ret;
pthread_join(thread, ret);
原因:pthread_join中有一句类型这样的语句:(* value_ptr) = arg;如果按照正确的方式传递参数,左边的语句实际上完成的操作是:ret = arg;一点问题没有。但是,当按照错误的方式传递参数时,会出现一句致命的错误:(* value_ptr),它对一个还没有初始化的指针进行了取值操作,这是系统所不允许的,此时(* value_ptr)等价于*ret,*ret还是一个指针,是一个二级指针,但是*ret是一个野指针!
注意啊!你返回的是一个一级指针,那么存储就只能是用 * &ret 来存储(希望你懂,就是指针降级)=ret;
那么输出自然也就是 ret了。
下面是一个例子:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
#define N 64
int a = 10;
void * handler(void *arg)
{
printf("a=%d, %s\n", a, (char *)arg);
strcat((char *)arg, " ......");
pthread_exit(arg);
}
int main()
{
pthread_t tid;
char buf[N] = {"welcome"};
void *result;
if (pthread_create(&tid, NULL, handler, (void *)buf) != 0)
exit(-1);
printf("*\n");
pthread_join(tid, &result);
printf("ret:%s\n", (char *)result);
return 0;
}
对线程等待函数pthread_join二级指针参数分析的更多相关文章
- C++ 有关指针作为函数参数的问题,自定义内存分配函数传递二级指针的问题
如题所示,我们主要讨论在自定义的内存分配函数中通常见到的代码如下所示: void Create(A** addr); 其中传递的参数是二级指针.为什么? 我们先看一下完整的动态内存分配函数的简单例子: ...
- WPF 自定义快速实现线程等待函数FastTask
在WPF实现 我们常常需要实现这个目标:线程里面执行复杂的任务,然后主窗体等待动画 我把我最简单的东西给包了一下,更方便使用,大家也可以方便使用 1:添加CommHelper类 FastTask方法 ...
- C语言深度剖析-----数组参数和指针参数分析
数组退化的意义 当向函数传递数组时, 二维数组参数 等价关系 注意事项 只能去一维数组 无法向一个函数传递一个任意的多维数组,注释地方出错 传递与访问二维数组的方式 动态地算出二维数组的列
- C语言的本质(16)——函数接口的传入参数与传出参数
如果函数接口有指针参数,既可以把指针所指向的数据传给函数使用(称为传入参数),也可以由函数填充指针所指的内存空间,传回给调用者使用(称为传出参数),例如strcpy的函数原型为 char *strcp ...
- C++二级指针和指针引用传参
前提 一级指针和引用 已经清晰一级指针和引用. 可参考:指针和引用与及指针常量和常量指针 或查阅其他资料. 一级指针和二级指针 个人觉得文字描述比较难读懂,直接看代码运行结果分析好些,如果想看文字分析 ...
- 【C】二级指针探秘 & 星号的两种用法(1.与基本类型结合形成另一种类型,比如与int结合形成int* 2.取值操作)
1)问题:二级指针到底是什么?怎么用的?怎么存放的? #include <stdio.h> #define TEST_ADDR 0x12FF40 void main() { int a = ...
- C#中调用C++的dll的参数为指针类型的导出函数(包括二级指针的情况)
严格来说这篇文章算不上C++范围的,不过还是挂了点边,还是在自己的blog中记录一下吧. C++中使用指针是家常便饭了,也非常的好用,这也是我之所以喜欢C++的原因之一.但是在C#中就强调托管的概念了 ...
- C-指针,二级指针,二维数组作为函数参数使用,C语言链表(详解)
一级指针 int *p; //表示定义一个int型(4字节)的指针p &p //表示p自身的地址位置 p ...
- FreeRTOS信号量的封装函数参数是二级指针
1. 先看正确的封装方式,问题所在,为什么要用2级指针 void cissys_lockcreate(void** mutex) { //创建信号量,应该是互斥锁 *mutex = ((Semapho ...
随机推荐
- JMS
发消息 与 收消息 http://www.huaishao8.com/config/activemq/143.html http://yingzhuo.iteye.com/blog/1566612 h ...
- golang: 常用数据类型底层结构分析
虽然golang是用C实现的,并且被称为下一代的C语言,但是golang跟C的差别还是很大的.它定义了一套很丰富的数据类型及数据结构,这些类型和结构或者是直接映射为C的数据类型,或者是用C struc ...
- oracle中merge方法
先看SQL语句:merge into employee e using emps em on (e.emp_id=em.emp_id) when matched then update set e. ...
- SqList *L 和 SqList * &L的区别/学习数据结构突然发现不太懂 小祥我查找总结了一下
小祥在学习李春葆的数据结构教程时发现一个小问题,建立顺序表和输出线性表,这两个函数的形参是不一样的. 代码在这里↓↓↓ //定义顺序表L的结构体 typedef struct { Elemtype d ...
- 【leedcode】longest-substring-without-repeating-characters
Given a string, find the length of the longest substring without repeating characters. Examples: Giv ...
- QT 调用VS2015编写的Dll
最近在用QT调用VC生成的库,QT使用的是MinGW调试器,出现与动态库不兼容的问题,最后发现QT只能识别VC生成的C格式下的动态库 也就是在导入导出设置时加入extern "C" ...
- PHP无限极分类,多种方法|很简单,这里说的很详细,其它地方说的很不好懂
当你学习php无限极分类的时候,大家都觉得一个字"难"我也觉得很难,所以,现在都还在看,因为工作要用到,所以,就必须得研究研究. 到网上一搜php无限极分类,很多,但好多都是一 ...
- 不同数据库中同一张表的SQL循环修改语句
select sample_value,Sample_GUID,row_number() over(order by sample_value )as rownumber into #AATemp ...
- cygwin 安装apt-cyg命令
googlecode关闭了.没法用wget安装apt-cyg 找了半天只有github里有个方法可行: apt-cyg is a simple script. To install: lynx -so ...
- [转]spring_bean的属性
1.parent 表示继承的父类 如果有很多继承同一个父类的BEAN 那么在配置文件中实例那些BEAN时候可以省略掉父类已经注入的属性 bean定义继承父bean定义,它可以覆盖父bean的一些值,或 ...