C语言进阶篇(指针进阶)

字符指针

表示为char*,常有两种表现形式:

字符用单引号' '引用,字符串用双引号" "引用。 

分析:

当强行改变b的数据时,此时程序会挂掉,但不会报错

为了防止这种错误的发生,我们常在char前加个const,即:

这样有效的保护了b的数据,可有效的发现错误。

对以下结果进行分析:

p1和p2均存放的是首字符a的地址所以相等(不加const结果也一样)。

而arr1和arr2要想存放字符串必须开辟一块空间,那么这两块空间的地址必然不一样,则首字符的地址必然不一样。

指针数组

概念:是用来存放指针的数组

实例分析:

arr1,arr2,arr3均存的是数组里首元素的地址,即arr1存的是1的地址,arr2->2,arr3->

所以要用int*来接收地址。

通过以上代码可完整打印所有元素

*(parr[i]+j):parr[i]能指明具体数组(arr1等),parr[i]+j说明跳过j个元素,也就是在某一数组跳过j个元素。

注:j<=元素个数-1,若j>=元素个数,并不会跳入下一个数组,而是会发生越界访。

数组指针

数组指针的定义

分析以下两种情况:

p1是指针数组,

p2是数组指针,指向一个数组,而数组里有十个元素,每个元素都是int类型。

注意:[]的优先级要高于*,所以必须要用()来确保p和*结合。

对数组的认识:

在 C 语言中,数组名一般代表数组首元素的地址,但有两个例外情况:

  1. 当数组名出现在sizeof()里时,它代表整个数组,此时sizeof(数组名)计算的是整个数组所占的字节大小。
  2. 当数组名前加&(即&数组名)时,它也代表整个数组,所以&数组名获取的是整个数组的地址(虽然和首元素地址的数值相同,但含义和步长不同)

整形指针是用来存放整形的地址。

字符指针是用来存放字符的地址。

数组指针是用来存放数组的地址。

则可得到

注:*并不是解应用操作符,*只是说明p是指针,里面存放的是地址。

同样,这说明pc里存放的是整个arr的地址,arr里的每个元素都是char*类型。

上图写法是错误的,若要运行正确,则必须写明元素个数,并且元素个数要相同(第一行代码的个数可不用写)。

改正后:

打印数组的方法

常见方法:

还可通过以下方法打印数组元素:

分析:p是指向数组arr的,所以*p就相当于数组名,而数组名又是指首元素的地址,所以*p就是指首元素的地址,则*p+i相当于跳过了i个元素,最开头的*是解应用操作符。

打印二维

数组:

分析:arr相当于第一行所有元素的地址,因为二维数组的首元素是它的第一行。

以上两种写法是等价的

对数组指针表现形式的分析

int (*p)[5]:

p的类型为:int(*)[5]

p是指向一个整形数组的,数组有5个元素

p+1是指跳过一个有5个元素的数组

数组参数_指针数组

一维数组传参

结论:以上写法均可

数组传参,形参的部分可写成数组也可写成指针,实参和形参的类型要一致

对test2()进行分析:数组名arr2表示的是首元素的地址,所以用可以用int*来接受(可将arr[20]看成一个接受地址的数组;而int**arr是二级指针,用来存放一级指针变量(即arr2)的地址,故也可。

二维数组传参

      

二维数组arr表示的是首行元素的地址,首行是一个一维数组        

对第一个(int*arr)进行分析:不可;这样int*arr只能接收第一行第一列的地址了。

对第二个(int*arr[5])进行分析:不可;地址要用指针来接收,而int*arr[5]是指,用数组接受,数组里每个元素的类型是int*。(应去掉*)

对第三个(int(*arr)[5])进行分析:可;*arr接收了arr数组首行的地址。

对第四个(int**arr)进行分析:不可;

一级指针传参

传过去的实参类型与接收的形参类型一样就可以成功传过去

二级指针传参

函数指针

概念:指向函数的指针就是函数指针 

       

结论:对于函数来说,&函数名和函数名都是函数的地址

函数指针的写法

类似与数组指针

其中 x ,y均可省略,只需把其类型交代清楚即可        

对于最后一段代码,*可省略,也可加多个,因为*在此并不起作用,只是便于理解。

实际用处:

分析:  void(*p)();其中p是函数指针,而void(*)()是函数指针类型,并且是强制类型转换

  0本来是int类型,强制类型转换后说明是

结论:以上代码是一次函数调用操作,具体是调用内存地址 0 处的函数:

  1. 把数值 0 强制转换成 “无参数、返回值类型为 void 的函数” 对应的地址类型
  2. 调用位于地址 0 处的这个函数

分析:signal是函数名,这段代码是它的函数声明。

  • 该函数的第一个参数类型是int;第二个参数是函数指针,指向的函数是 “参数为int、返回类型为void” 的函数。
  • signal函数自身的返回类型也是一个函数指针,指向的同样是 “参数为int、返回类型为void” 的函数。

简化版:

typedef是用来重命名类型的函数,通常写法为:

typedef unsigned int uni_t:unsigned int是要重命名的类型,uni_t是重命名后的名字

而重命名函数指针时,应用上图写法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值