四、指针高级应用总结

四、指针高级应用总结

1 笔试积累

  • 指针数组本质是数组,数组元素全为指针。

  • 数组指针本质是指针,指向的是一个数组。

  • typedef的意义在于简化书写和创造平台无关性

  • typedef重定义的类型不会原地展开,也就是说经其被重定义的类型享有编译器与原生类型同等的待遇。而#define宏定义会原地展开。

  • 使用typedef可以同时定义出结构体变量和该结构体指针。

  • 二重指针本质仍然是指针变量,只不过其指向的变量类型是一重指针(普通指针)。

  • 数组初始化时,可以在大括号内直接使用下标指定初始化特定元素,例如int a[10] = {[3]=3};,其存在的意义为可以省略依次书写时,对前面元素的初始化操作。

2 理解和思想

2.1 先后结合看本质

  • 在复杂表达式中,若没有小括号的处理,则必须依据优先级进行结合处理。
  • 由于括号优先级较高的原则,可以判定int *p[10];中,p首先和括号结合,也就是说符号p的本质是一个数组,由于其类型为int *,可知该数组中每个元素均为指向int类型的数据的指针。
  • 同理可判断int (*p)[10];本质是一个指针,其指向的是一个具有5个元素的数组,每个元素的数据类型为int
  • 符号本质判定:先与*结合为指针,先与[]结合为数组,先与()结合为函数

2.2 函数指针的本质

  • 函数指针本质也是指针变量,只不过其指向的数据是一段代码的起始地址。
  • 指针变量指向的数据内容依据其定义的类型,例如普通整型指针int *p;其指向类型为int *,数组指针int (*p)[10];其指向类型为int (*)[10],而函数指针int (*pfun)(int);其指向类型为int (*)(int);即指向一个返回值为int,有一个输入参数且为int类型的这样的一个函数。
  • 函数名称前取地址&pfun其意义及数值均和函数名pfun一致,这一点需要区别于数组名。

2.3 typedef与指针

  • typedef经常被用来简化函数指针的书写样式,然后便于将函数指针封装在结构体内部,间接完成面向对象编程的功能,其目的也是为了代码结构清晰,简化复杂程序代码量和统一抽象代码逻辑。
  • 使用typedef定义的类型可以连续定义多个指针变量typedef int * user_t ; user_t a,b,c;,但#define user_t int*则定义多个变量后原地替换int * a,b,c,相当于int *a;int b;int c;。也就是说指针类型(如int *)并不会被编译器接受为一个原生类型,除非typedef重定义。

2.4 const限定失效

  • 经过typedef重定义后指针类型加const限定会出现看起来失效的现象。
  • typedef int * user_t ;const user puser const p均等同于int * const p2。也就是说重定义int *未被限定,则使用该重定义时将无法更改他的限定关系,也就是说前面两种情况const都只能修饰指针p,而无法修饰其指向的数据。如果确实需要限定其指向的内存数据,那么就必须要在重定义时进行限定,一旦重定义完成,该原型将被保护。

2.5 双重指针本质

  • 都是指针变量,表现为其长度均为4个字节(32位系统)。
  • 指针如何指向另一个变量?指针变量本身存储的是另一个变量的地址。
  • 二重指针存储的是什么?存储一重指针变量的地址。即二重指针指向的是一个普通指针变量。
  • 编译器类型匹配检查中,举例二重指针int **p指向int *类型,那么指针数组int *q[3]的数组名q与二重指针p类型匹配,分析:数组名是该数组首元素首地址,该数组首元素是一个指针q[0],对该指针变量取地址即为数组名q,也就是说其数组名就是一个二重指针。

2.6 数组名和指针类型匹配

  • int a[10]一维数组名即为首元素首地址&a[0],也就是可以被一个普通的一维指针所指向的地址。即int *p = a;是类型匹配的,由此可以推断,二维数组中类型匹配时,将此处的p指向一个普通int类型变量替换为指向一个一维数组且数组元素为int类型即可。
  • int b[5][10]二维数组名即为首元素首地址&b[0],只不过需要注意的是,这里的首元素是仍然是一个一维数组,也就是说b[0]仍然可以作为一个数组名,即等价为&b[0][0],所以综上可得b等价为&&b[0][0]。因为需要使用一个合适的类型与数组名匹配(两个取址符),此时的数组名表示的是一个数组**(元素个数为10的int 类型数据)的首地址,而能指向一个数组的首地址的指针变量可以是数组指针(指向元素个数为10的int 类型数据)**,即int (*p)[10] = b;是类型匹配的。

2.7 数组的指针访问

  • 首先需要明确数组下标访问其本质是编译器在使用指针访问。

  • 一维数组和二位数组在访问效率上无任何差异,其目的只有一个,方便程序员编写代码。

  • 掌握指针访问数组元素的关键是:指针步进值,也就是指针在与数字运算时的意义。

  • 一维数组及指针int a[10] ; int *p = a ;,访问元素a[3]即相对于首元素移动了3个步进值即可,而由指针p定义可知,该步进值为sizeof(int)=4。直接使用*(p+3)即可访问a[3]

  • 二位数组使用指针方式访问,需要两次解引用,第一次解引用得到在一维数组中的指针位置,之后步进值由原来的一维步进值(即指向的数组的长度)变为二维步进值(指向变量类型的大小)。int b[5] [10]; int ( *p )[10] = b;* (p+1)取得a[1]地址,实际上+1操作是对指向的数组进行操作,步进值为10*4,也就是说指针实际移动了1*40=40个单位。经过一次解引用过后步进值变成了指向变量的步进值4,接着*(*(p+1)+2)即从a[1][0]移动到了a[1][2],实际上+2操作指针移动了2*4=8个单位

  • 二维数组使用指针访问时也可以采用一维数组指针访问的方法,只不过需要自己计算,例如int b[5] [10]; int *p = &b[0][0];,访问a[1][2],需要计算偏移量,且只能一次解引用(因为是一个一维指针):*(p+1X10+2),即*(p+12)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fffxxx222

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值