学习数组指针、指针数组、二级指针的心得体会

前言

近些天探究Linux内核双链表部分的知识进程缓慢,发现其根源还是基础不牢固,之前对C语言的学习只停留在做题的层面,对一些概念理解的迷迷糊糊,这几天我重新学习了指针部分,也就是C语言中的难点部分。发一篇博客来说说困扰了我好几天的数组指针、指针数组以及二级指针。

概念

数组指针:首先数组指针是一个指针,指向数组地址,它指向的是数组中的具体元素,并不是整个数组,所以说数组指针的类型和数组元素的类型有关,在32位系统下永远占4个字节。

指针数组:首先指针数组是一个数组,数组中的元素都是指针,数组占的字节数由数组本身决定,数组中的每个元素都是指针。

二级指针:通过指针变量可以访问数组元素,要求它的类型必须是指向该元素类型的指针类型。那么想要通过指针变量访问指针数组的元素,就必须定义二级指针,即为指向指针的指针,用二级指针变量指向指针数组的各元素。

演示

判断指针数组与数组指针

int (*a)[5];
int *b[5];
  • ()的优先级比[]高,所以*号与()先构成一个指针的定义,该指针变量名为a,int即为数组中每个元素的类型,a是一个指针,指向一个包含5个int类型数据的数组,即数组指针。

  • []的优先级比*高,所以说b先与[]结合构成一个数组,b为数组名,int是数组里每个元素的类型,数组中包含5个指向int类型数据的指针,即为指针数组。

关于数组指针

我们正常定义一个指针变量都是直接加在指针类型后面的,比如说:int (*)[5] p 这种样子,通过查阅资料,数组指针的原型的确如此,只不过为了美观将指针变量前移了而已。

利用指针遍历数组元素

#include <stdio.h>
int main(void)
{
    int arr[]={1,2,3,4,5,6,7,8}               //定义数组
    int len;
    len=sizeof(arr)/sizeof(int);              //数组的长度
    int i;
    for (i=0;i<len;i++)
    {
        printf("%d",*(arr+i));                //*(arr+i)即为arr[i]
    }
    printf("\n");
    return 0;
}

这里arr是数组名,表示数组首元素的地址,arr+i指向数组的第i个元素,*(arr+i)表示取数组中第i个数据,等价于arr[i],这里的arr是int *类型的指针,arr每加1,自身就会加上sizeof(int),也就是4,arr+i也就是自身的值加上i * sizeof(int)

利用数组指针遍历数组

#include <stdio.h>
int main(void)
{
    int array[]={1,2,3,4,5,6,7,8};
    int len;
    len=sizeof(arr)/sizeof(int);
    int *pp=arr;
    int i;
    for (i=0;i<len;i++)
    {
         printf("%d",*(pp+i));
    }
    printf("\n");
}

这里的sizeof(arr)不可以换成sizeof(pp),因为这里的pp是变量,而arr是字符常量,编译器不能明白pp指向的是一个元素还是整个数组,所以这里的sizeof(pp)求的仅仅是这个指针变量所占有的字节数,在32位系统下也就是4,并不是整个数组所占的字节数。

所以说,通过上述两个例子我们不难发现,要想访问数组元素,可以通过数组下标或者指针来进行。

使用下标

用arr[i]的形式访问数组元素,如果指针pp指向arr,也可以用pp[i]来访问数组元素,其等价于arr[i]。

使用指针

也就是通过 *(pp+i)的形式来访问数组元素,其等价于 *(arr+i),因为arr本身也是指针。

所以说不管是用数组名还是数组指针都可以访问数组元素,不同的是数组名是字符常量,不能随意改变,它只能指向数组的开头,而指针变量即可以随意改变,既可以指向数组开头,也可以指向数组任意位置,这点一定要注意。

例子如下图

#include <stdio.h>
int main(void)
{
   char *pp[5]={"mmhdsg1997715","building","linux","interesting","funny"};
   char *str1=pp[1];
   char *str2=*(pp+2);
   char a=*(*(pp+2)+4);
   char b=(*pp+3)[2];
   char c=*pp[1]+3;
   printf("str1=%s\n",str1);
   printf("str2=%s\n",str2);
   printf("a=%c\n",a);
   printf("b=%c\n",b);
   printf("c=%c\n",c);
   return 0;
}

运行后的结果如下图:

str1=building
str2=linux
a=x
b=g
c=e

这里的pp为二级指针,也就是指向指针的指针,所以*(pp+i)为指针, **(pp+n)为具体的字符。

答案解释

1 、这里的pp[1]即为*(pp+1),它是一个指针,指向字符串str1。

2、这里的*(pp+2)即为pp[2]。

3、这里的*( *(pp+2)+4 )可以写成 *(pp[2]+4),其中pp[2]+4就是字符串"linux"第四个字符的地址(指针就是地址),所以 *(pp[2]+4)就是"linux"第四个字符即为’x’。

4、这里的(*pp+3)[2]可以写成( *(pp+0)+3)[2]等价于(pp[0]+3)[2]等价于 *((pp[0]+3)+2)等价于 *(pp[0]+5),即为字符串"mmhdsg1997715"第五个字符’g’。

5、这里的*pp[1]+3即为 *(pp[1]+0)+3为字符串"building"的第0个字符’b’的ASCII码值加上3,即为字符’e’。

总结

希望自己的总结能帮助到大家吧!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值