线程中遇到pthread_create函数第三个参数 void *(*start_routine)(void *)
这个参数代表一个指针,这个指针指向的函数必须满足以下条件:
1、函数参数只有一个为void指针,可以为任意数据类型的指针。
2、函数的返回值必须是void指针,可以为返回任意数据类型的指针
指针函数:函数返回值为指针的函数。
函数指针:指向函数名的指针为函数指针。
eg:这里有个函数是 void *func( void *)
我们用一个指向函数名的指针来做pthread_create的第三个参数
函数名指针有个特殊的地方:函数名可以直接做为指向函数的指针来使用。
定义指向函数的指针是根据函数的参数来定义的。
比如有个函数
int max( int x, int y );
我们要定义一个指向max函数的指针,我们可以这么定义 int (*p)(int,int); p=max;
这样我们就定义了一个指针p指向函数样式为 int xx(int, int)类型的函数。
这里的*p必须用括号括起来,如果不括起来编译器会认为定义了一个函数,函数的返回值类型是一个指针。
根据pthread_create的定义,我们需要给他传送一个指向 void *XXX( void * )的指针。
所以我们通常会定义一个处理函数:
void *thr_fn( void *arg )
{
printids(arg);
return NULL;
}
然后有些书上在调用pthread_create第三个参数时候喜欢写成 (void *)*thr_fn
这里做一下说明。其实我们可以直接用 (void *)thr_fn来代替他,因为thr_fn本来就是一个指针。指向自己这个函数的地址。所以我们不需要再另外定义个 void *(*p)( void *
)来保存这个函数的地址了。
所以下面几条语句是等同的
1、pthread_create( &tid, NULL, (void *)thr_fn, “hello” );
2、void *(*p)( void * ); //首先定义个指向该函数的指针
p = thr_fn;
pthread_create( &tid, NULL, p, “hello” );
3、pthread_create( &tid, NULL, thr_fn, “hello” ); //建议写法
4、pthread_create( &tid, NULL, (void *)*thr_fn, “hello” ); //书上标准写法
5、pthread_create( &tid, NULL, (void *)**thr_fn, “hello” );
6、pthread_create( &tid, NULL, (void *)***thr_fn, “hello” );
…
这里要说明的是 函数名作为的地址比较特殊。如果我们试着对函数名取值*thr_fn,发现取值后的地址还是个地址,也就是本身thr_fn的地址。所以不管多少次*取值都会得到同样
的结果,函数名指针就有这样一个特殊之处。换作其他变量的指针,多次用*取值后系统会找不到值,会报错。
这里有几个实例
#include <stdio.h>
int main()
{
int a=3;
int *p = &a;
printf( "%x\n", (int)p );
printf( "%x\n", (int)&p );
/* printf( "%x\n", (int)&&p ); 对地址的位置进行取地址,编译器报错 */
printf( "%x\n", (int)main );
printf( "%x\n", (int)*main );
printf( "%x\n", (int)**main );
printf( "%x\n", (int)***main ); /* 多次*取值不会报错,函数名指针特殊性 */
printf( "%x\n", (int)&main );
return 0;
}
RedHat freelh~/pthread >gcc -Wall -o test2 test2.c
RedHat freelh~/pthread >./test2
bfffeb64
bfffeb60
8048328
8048328
8048328
8048328
8048328