程序设计与C语言学习笔记_第七章指针

7章 指针

7.1 指针的概念和定义

1. 指针的概念:指针就是内存地址,可以是简单变量、复杂变量、函数等的内存地址。

2. 指针的定义:int * yptr;yptr为指向整型变量的指针。

7.2 指针运算

7.2.1 指针运算符

1. 地址运算符&:返回变量在内存中的首字节的地址,单目运算符,优先级很高,右结合性。

2. 间接引用运算符*:又称复引用运算符,作用在指针变量和内存地址上,返回指针所指向的对象的值,单目运算符,优先级很高,右结合性。

3. 要注意的问题

1) &和*对指针变量有互补性。

2) 指针变量可以赋值为0和NULL,表示不指向任何对象。

(1) NULL为头文件stdio.h中定义的符号变量。

(2) 指针变量除了赋值为0和NULL外,只能赋值为地址。

(3) NULL更好一些。

3) 不同类型的指针变量之间不能相互赋值。

4) 指针变量指向未定时,不能对其所指内存位置输入值,否则可能会破坏系统的重要数据。

7.2.2 指针作函数参数

1. 把函数的形参定义成指针类型,而将实参也定义为指针类型或变量的地址,这样就可以实现“传址调用”

7.2.3 最低访问权原则和const常量限定符

1. 用于传值调用

1) int i=1:不做const常量限定,可以任意改变i的值。

2) const int i=1:做const常量限定,i的值不能变化。

2. 用于传引用调用

1) int * i=&j:不做const限定,可以任意改变指针i及其所指内存变量的值。

2) const int * i=&j:指向常量的非常量指针。

3) int * const i=&j:指向非常量的常量指针。

4) const int * const i=&j:指向常量的常量指针。

3. 注意的问题:

1) const限定时,被限定的变量在定义时必须得赋值,不然后面就不能赋值了,编译也会出错。函数调用则也是一样的道理:在参数赋值时,即相当于定义时赋值,如函数void printa(int b[],const int s)。

7.2.4指针运算

1. 指针加、减运算

1) 指针的加、减运算的前提条件是指针已经指向一个数组,否则运算是无意义的。

2) 对指针进行加、减运算,根据指针指向数据的类型,来确定指向移动多少字节。同样数组中下标的加减和数组地址,也根据数组元素的类型,来确定移动多少字节,如:a[i+1]、&a[0]+1。

3) 如果两个指针指向同一个数组,则它们之间的减法运算,代表两个指针指向的对象之间的位置差距。位置差距默认指的是数组元素的间隔,而不是字节的间隔,如果要求字节差距,可在指针变量或地址变量前加(int),将地址强制转换为整数变量。

2. 指针的比较运算

7.3 指针与数组

7.3.1 一维数组与指针

1. 一维数组的地址和指针的关系

1) 一维数组的数组名代表数组第一个元素的地址;当指针指向数组第一个元素时,指针变量和数组名是可以相互替换的。本质上来说,数组名就是指针,数组的方括号运算其实就是指针的加减运算。

2. 一维数组元素的表示方式

1) “数组名+下标”表示法

2) “数组名+偏移量”表示法

3) “指针名+下标”表示法

4) “指针+偏移量”表示法

3. 数组和指针作函数参数

1) 实参和形参全是数组名。

2) 实参是数组名,形参是指针。

3) 实参是指针,形参是数组名。

4) 实参、形参全是指针。

7.3.2 字符指针

1. 概念:指向字符变量的指针,字符串有两种实现方法:字符数组,字符指针。

2. 定义:char * str

3. 要注意的问题

1) 用字符指针实现字符串时,有两种赋初值的方法:

(1) char * str=“abcdef”

(2) 字符指针构成的字符串可以使用赋值号进行赋值,字符数组构成的字符串却不行:

[1] char * str;str=”abcef”“abcef”代表字符串的首地址,也代表这个字符串!

[2] char * str1,* str2;str1=“abc”;str2=str1。

7.3.3 二维数组的地址及指针

1. 二维数组的地址

1) 列地址:数组元素的真实地址,如a[O][3],a[3]等。

2) 行地址:数组的行的首地址,如a,a+1等;

3) 列地址与行地址的关系:*(a)=a[0]=&a[0][1]

4) 要注意的问题:

(1) 二维数组名代表的是首行的地址,是行地址。行地址比列地址高一级别。

(2) a[0]/a[1]/a[2]代表的第0、1、2行的首地址,是列地址,也可以代表第0、1、2行这个数组的名字。

(3) &a[1][2]+1表示&a[1][3],与一维数组加减法相同。

(4) &a[i][j]=&a[0][0]+i*n+j,二维数组有n列。

2. 用列地址、行地址表示数组元素

1) 用列地址表示数组元素:*(a[1])=*(&a[1][0])=a[1][0]

2) 用行地址表示数组元素:*(*(a))=*(&a[0][0])=a[0][0]

3. 指向二维数组的指针

1) 二维数组的列指针:

(1) 概念:与一般指针是一样的。

(2) 定义:int * p,*l;p=&a[2][3];l=a[0]。

2) 二维数组的行指针:

(1) 概念:用行指针来处理二维数组是,行指针定义的长度应等于二维数组的列数。

(2) 定义:int (*p)[4],a[3][4];p=a

4. 行指针作为函数的参数

1) 利用函数对二维数组进行处理时,可以以二维数组名作为实参传递给函数,函数以行指针为形参来接收它。

7.3.4 由指针组成的数组

1. 定义:如int * a[3];表示3个指向整型数据的指针数组。

7.3.5 二级指针

1. 概念:将地址的地址放入某个变量中,则这个变量就是指向指针的指针变量,因而被称为二级指针。

2. 定义:如:char * * p,*pname[2]={”abc”,”def”;p=pname;p为二级指针。

7.3.6 二维数组处理小结

7.3.7 main函数的参数

1. 当操作系统调用main函数生成的执行文件时,可能要带参数,这个参数也是main()函数的参数。

2. int main(int agrc,char * argv[])

1) argc[]:字符指针(字符串)数组代表操作系统输入的命令,如 append file1 file2,程序不能对可执行文件名argv[0]进行引用。

2) agrc:argv数组的元素个数。

7.4 指针与函数

7.4.1 指向函数的指针

1. 函数指针的定义与引用

1) 函数指针定义的一般形式:如int (* p)(int,int),p为函数参数为俩整型数据的函数指针。

2) 函数指针的引用,将函数名赋值给函数指针,函数指针和函数名等价。

3) 需要注意的问题

(1) 函数名代表存放函数代码的内存首地址,即函数入口地址。对函数名使用加减法无意义。

(2) 函数指针只能指向同一类的函数。

2. 函数指针作函数参数

7.4.2 返回指针的函数

1. 返回指针类型的函数的一般形式:int * p(int,int)

7.4.3 从被调函数中获取数据的渠道

1. return

2. 全局变量

3. 传址调用

4. static变量;return 静态变量,return的不是copy,而是静态变量本身,相当于传址调用。

7.4.4 悬空引用

1. 概念:函数被调用后,系统会给其定义的变量分配临时空间,而一旦调用结束后,临时空间会被收回,而如果把变量地址返回给主函数,主函数在使用引用该地址变量时,就会出现悬空调用。

2. 预防悬空调用:

1) 将变量设置为static变量,调用结束后,临时空间不会被收回。

2) 在主函数定义变量,然后传址调用。

7.4.5 二级指针做函数参数

7.5 多级指针

7.5.1 多级指针的定义

7.5.2 多级指针与多维数组

1. 多维数组

用指针处理多维数组

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值