1、前言
1)指针变量如同int变量一样,在函数中,存储在栈区,此时为局部变量。其标志是 *,可以理解为其类型是个*;
2)不论指针变量指向的是何种变量,对于指针变量来说所占字节都是一样的,
例如:
int *p 和double *q, p和q都是占4个字节,
不同的是,p++ 和q++,前者挪动了4个字节,后者挪动了8个字节
3)指针变量存的是个地址,即存储是个整型值。
int a =1;
int *p = &a;
printf("%d\n",(int)p);//打印出p是十六位进制数
2、一重指针的理解
int a =2;
int *p = &a;
p前面有个*,表明变量p是个指针,指向的是*前面的数据类型int;
函数中,形参传递指针,可以改变实参解引用 的值大小
void func(int *para)
{
*para = 2;
}
int aa = 1;
func(&aa);
printf("%d",aa);//aa的值变为2
3、二重指针的理解
int a =2;
int *p = &a;
int **q = &p;
同一重指针p一样分析,q前面有个*,说明q是个*型变量,即是指针,指向的数据类型是个 int*,即指向指针的指针,为二重指针。
同一重指针一样,函数中形参是二重指针(也是个指针),可以改变实参解引用 的值,实参解引用是一重指针,改变了一重指针的值,就是改变了一重指针指向的内存单元。
void func(int **para)
{
*para = (int*)malloc(sizeof(int)*3);
}
int aa = 1;
int *p = &aa;
func(&p);
printf("%d",(int)p);//p的值发生改变,指向了新的内存
小结:函数形参为一重指针时,会先定义一个普通变量A--->取地址 变为实参B代入;
函数形参为二重指针时,会先定义一个一重指针变量A--->取地址变为实参B代入。
原因是想要进行指针传递,改变A的值,倘若直接定义实参B的,相当于是值传递,不会改变原值了。
函数参数为指针传递的形式,相当于给变量A加了一层保护,实参B的传递,是值传递(也就是复制),可以有多个,但是A只有一个,而且自始至终都是这一个。
我们以以下例子来分析二重指针的传递:
phtread_exit(void *ptr);
phtread_join(pthread_t thread,void** retval);
我们知道ptr的值返回给retval的。
我们分析一下,为什么ptr是一重指针的时候,retval是二重指针?
由以下例子可以看出,我们在main函数中通过pthread_join 获得ptr的值。void*ptr 是一重指针,我们要将其赋值给同样的一重指针char* thread_res(未初始化);
我们知道要对一个未初始化的变量代入函数中进行初始化的方式有两种:一种是指针,一种是引用,很明显函数采用了指针的方式来传递,char* thread_res是一重指针,形参retval是* 的话,只是值传递(对于未初始化的变量来说,不允许),所以,此处是**,即二重指针传递。
void *func(void *arg)
{
char *s = (char*)malloc(10);//动态赋值,存储在堆,可以带到函数体外
strcpy(s,"hallow");
pthread_exit((void*)s);//返回值是s的拷贝
}
int main()
{
int res;
pthread_t a_thread;
char* thread_res;
res = pthread_join(a_thread,&thread_res);
printf("thread finished! return value:%0x --- %s\n",thread_res,(char*)thread_res);
free(thread_res);//将func函数中的malloc的内存地址释放
thread_res = NULL;//此处只能将thread_res置空,而无法将func中s置空
exit(EXIT_SUCCESS);
}
个人理解,thread_res = NULL;//此处只能将thread_res置空,而无法将func中s置空,因为phread_exit(void *ptr);
倘若phread_exit(void *ptr)是通过** 二重指针传递到pthread_join的话,就可以将s置空。