高级指针概念和应用

一:数组指针和指针数组的理解:

1.首先我们从一个例子开始讲起

include<stdio.h>

int main()

{

int a[5][5]={0};//创建一个二维整型数组,并初始每个元素化为0;

int(*p)[4]=NULL;//定义一个数组指针,这个指针指向大小为四,并且每个元素为int型的指针,将此指针初始化为空;

p=(int(*)[4])a;//二维数组的数组名a,代表一个大小为5,每个指针指向5个元素的指针数组;而此时的p为一个可以指向

                    //四个元素的指针,所以此时要给a强制类型转换为指向四个int类型元素的数组指针,再付给p;

printf("%p,%d",&p[4][2]-&a[4][2],&p[4][2]-&a[4][2]);

return 0;

}

结果为

详细分析:

对于最后一行的分析:

printf("%p,%d",&p[4][2]-&a[4][2],&p[4][2]-&a[4][2]);


(1)指针减指针输出的是元素个数,又因为p[4][2]的地址小于a[4][2]的地址;

所以如果以%d的格式输出来直接就是-4;

(2)printf函数族中对于%p一般以十六进制整数方式输出指针的值,附加前缀0x。

所以把-4用十六进制输出,数字在内存中以补码的方式存在;

-4的32位二进制

原码为:10000000 00000000 00000000 00000100

反码(符号位不变,其余安位取反):11111111 11111111 11111111 11111011

补码(反码加1):11111111 11111111 11111111 11111100

将此补码转换成十六进制为:fffffffc

所以最后输出的是fffffffc    

(3)总结此题:本题考察的是指针的部署, int(*p)[4]=NULL,像这样的指针加1,则跳过了一个大小为四,每个元素为整型的数组;

  2.再看一个例子:              

#include<stdio.h>
int main()
{
int aa[2][5]={1,2,3,4,5,6,7,8,9,10};
int *prt1=(int *)(&aa+1);
int *prt2=(int *)(*(aa+1));
printf("%d,%d",*(prt1-1),*(prt2-1));
return 0;
}


(1)结果为:

(2)分析:


3.其实在指针这块还是很有趣的,

例如给出这样一个例子

#include<stdio.h>

int main()

{

int a[]={1,2,3,4,5,6};

printf("%d",a[2]);

printf("%d",2[a]);

}

(1)程序输出的结果为:

(2)分析:

因为a[2]相当于*(a+2)

然而2[a]的意义是*(2+a)

因为a代表首元素的地址,为整型,2也为整型,所以a和2顺序可以互换,不影响结果;


4.总结:

(1)数组指针:强调的是指针,它是一个指向数组的指针;int (*arr)[3];

(2)指针数组:强调的是数组,数组里面保存的是指针,数组的每个元素都是指针类型;int*  arr[3];

二:二级指针

1.概念:二级指针用来存放一级指针的地址。

2.格式:char**p

3.二级指针的内存分布:


三:数组参数和指针参数:

1.一维数组参数:

#include<stdio.h>

void fun(char arr[])//此时,可以不写形参数组的大小,因为此时只是定义了一个数组名字,并没有给这个数组开辟内存空间。                              

                            //因为,实参传过去的并不是整个数组,而是数组首元素的地址,所以不能用sizeof在函数内部求取                               

                          //整个数组的大小;求取的是指针的大小,为四个字节。所以,形参可以写成一个指针 void fun(char* arr),

{                           

char c=arr[4];

}                          

int main()

{

char arr[]="abcde";

fun(arr);//函数调用传递整个数组时,实参只需要写数组名即可,不可给数组名之后加下标;加了下标表示数组的某                  

           //个元素;此时其实并没有传递整个数组,因为数组名代表数组首元素的地址。

return 0;

}

2.一级指针参数:

(1)简单举例:

#include<stdio.h>

void fun (char*p)

{

char c=p[3];//等价于char c=*(p+3)

}

int main()

{

char* p ="abcdef"       //此时p的空间中保存地是字符a的地址;

fun(p) ;                      //传递a的地址;

return 0;

}。

3.二维数组参数和二级指针参数:

(1)首先从一例子开始分析:

include<stdio.h>

//viod  fun(int  **arr)。错误:传参时。不能用二级指针接受二维数组。

//viod  fun(int  arr[][])。错误:如果去掉后一个方括号中的数字3,则不能确定传进来的数组指针指向的数组的大小。

//viod  fun(int  arr[][3])  正确

//viod  fun(int  (* arr)[3])   正确

viod fun(int arr[2][3])

{

;

}

int main()

{

int arr[2][3];

fun(arr);  //数组名在传参的时候发生降级,表示数组首元素的地址;

              // 此时,这个二维数组的名表示一个数组指针,指向一个大小为三,每个元素类型为int的指针类型

               //也就是这样int (*)[3];

return 0;

}


(2)深入理解二级指针做形参的情况:

int fun(char** p)

//int fun(char* arr[])

{

;

}

int main()

{

char*pc;//一级指针

char  **ppc;//二级指针

char  *arr[3];/指针数组; 

fun(&pc);//二级指针就是用来存放以及指针的地址的。

fun(ppc)//二级指针传给二级指针,正确。

fun(arr);//因为此时arr为指针数组,数组的每个元素都是指针类型;而我们一再强调,

             //数组名代表数组首元素的地址;从而arr带表它的数组首元素指针的地址;

              //接收指针的地址当然要用二级指针去接收。

return 0;

}

(3)总结:

上面讨论的那么多,我们把二维数组和二维指针参数的等效关系总结一下;

a.当数组的参数为数组的数组,即二维数组时,如char  arr[2][2];

                           所对应的指针参数为 数组指针,char(*)[2]

b.当数组的参数为指针数组,例如:char * arr[5];

<span style="font-size: 18px

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值