函数传参过程中经常使用指针,其中最常用的是以及指针与二级指针。
数组与以及指针:
type a[N] = {0};与 type* a = calloc(N,sizeof(type))很相似,明显的区别是申请的堆内存需要自己释放,这也是的用户申请的这一块内存可以在程序的整个作用域中使用成为可能。
一级指针可以理解为某种类型的数组,元素之间的地址偏移为类型的长度sizeof(type),&a[i]与&a[i+1]或者a+i 与a+i+1之间的地址偏移为类型长度。
指针数组与二级指针:
type* a[N] = {NULL};与type** a;
二级指针:该变量值是一个指针1(某一地址),且该指针1指向一个指针2,指针2是指向type类型的指针。使用过程中通常也可以形式上理解为某一种类型的指针数组。
指针数组中每一元素之间的偏移为一个指针长度(4B),与指针类型无关。即&a[i]与&a[i+1]或者a与a+1的地址偏移为固定的4B。
在涉及函数传参中有数组或者指针结构的情形下明确一点:参数的传递的值传递,这个值既可以是地址值也可以是某一类型的变量值。
使用二级指针的情形:
1.为获得某一接口内部申请的内存需要使用二级指针
type* a = NULL;
fun_xx(&a);
2.为某一接口传递指针数组参数
type* a[N] = {xxx,xxx…}
fun_xx(a);
二级指针在使用过程中容易混淆的是地址偏移,例如给func_xxx(type** a)传参:
type* a = calloc(N,sizeof(type));
for(i = 0;i< N;i++)
{
a[i] .xx= xxx;
}
func_xxx(&a);
func_xxx期望传参的是一个指针数组type*a[N],直接传入已经初始化的内存的地址&a,由于a + i(i非0)的地址是只是相对与a的地址偏移4B*i,显然是非法访问的,与申请的内存没有关系,这样调接口是失败的。
正确的用法是传入记录申请内存单元地址的指针数组:
type** tmp = {&a[i],….}
func_xxx(tmp);