指针基本概念介绍_第1页
指针基本概念介绍_第2页
指针基本概念介绍_第3页
指针基本概念介绍_第4页
指针基本概念介绍_第5页
已阅读5页,还剩68页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第2-5讲 指针1基本概念介绍指针的基本概念指针与数组指针与字符串指针与函数指针与结构体引用的概念及应用15.1 指针的概念一、指针与地址指针是C语言中的一个重要概念。掌握指针的用法,可使程序简洁、高效、灵活。例如:寻宝游戏66 1000P2111000 P为指针变量,1000(地址)是指针变量的值。 指针变量就是用来存放另一变量地址的变量2计算机的内存是一些“存储单元”的系列集。每个单元(字节)有一个称为地址的数字与之关联。地址都是从0开始依次编号的。最后一个地址编号取决于内存的大小。64K 65535当声明一个变量时,系统会在内存中分配适当的存储空间,以保存该变量的值。内存单元地址0123

2、4567.655353 指针是建立在下面3个基本概念的基础上的: 计算机的内存地址是指针常量(pointer constant)。我们不能修改它们,只能用来存储数据值。 不能直接保存地址的值,只能利用地址运算符(&)来获取变量的地址。这样获得的值称为指针值(pointer value,也就是变量的地址)。指针值在程序每次运行时都会发生变化。 包含指针值的变量称为指针变量(pointer variable)指针相关的基本概念 指针常量 指针值 指针变量 指针4二、指针变量的声明 声明形式: 数据类型 * 指针变量名; “ * ” 表示这里声明的是一个指针类型的变量。 “ 数据类型” 是指针所指向

3、的变量的类型。一个指针变量只能指向同一个类型的变量。 例如: int * point_a; / 声明了一个指向 int 型数的指针变量 两种理解:1)(int *) point_a; / point_a 为 int * (整数指针)2) int (*point_a); / *point_a 为一个整数 注意: int * point_a, point_b; / point_b为intint * point_a, * point_b; / point_b为int *5在C/C+中,每个指针均有两方面的含义:内存存储单元和对存储单元内容的解释内存存储单元就是地址 指针本身只包含地址,要使用指针指向

4、的数据,必须先到达那个地址,提取并按一定规则解释该内存单元的内容。内存单元只不过是一些0/1位的组合。解释的基础依赖于指针的类型 整数指针表示指针指向一个整数,其真实含义是:程序从指针提供的单元地址提取整数所占字节数的0/1组合,即按整数编码规则解释。 例如:对同一存储单元,用几种方法解释得到不同的结果。6假设内存单元为(16进制): 0a 61 62 63 64 65 66 67 68 69 6a解释结果: int * :提取 0a 61char * :提取 0a float * :提取 0a 61 62 63long * :提取 0a 61 62 637三、与指针相关的运算符: & 和 *

5、 “ & ” 为取地址(引用)运算符,用来得到一个变量的地址。位于变量之前的地址运算符将可返回该变量的地址。运算符“&”只能用于单个变量或一个数组元素。&125 非法!指向了常量int x10 &x 非法!指向了数组名&(x+y) 非法!指向了表达式8必须确保指针变量总是指向相应的数据类型。 float a, b; int x, *p; p = &a; 错!可以把初始化和声明组合在一起。 int a, b; int *pt1, *pt2=&b; / 把变量b的地址赋给指针变量pt2 pt1 = &a; / 把变量a的地址赋给指针变量pt1唯一要求的是变量必须在初始化之前就已经声明过了。可以在定

6、义指针变量时带有一个初始值NULL或零。 int *p=NULL; /定义p为指向整形变量的指针变量, / 并初始化为0 int *p=0;9“ * ” 为间接访问运算符(或称“反引用”运算符),表示指针所指向的变量的值。 在声明语句中,“ * ” 表示声明的变量是一个指针。 int *point_a; 在执行语句中或声明语句的初值表达式中,表示访问指针所指对象的内容。例如: printf(%d, *point_a); / 输出指针 point_a 所指向的内容int a, *pt, b;a = 100;pt = &a; / 将a 的地址赋给指针变量ptb = *pt; / *pt返回的是变量

7、a的值a = *(&a) = *pt = n&a = &(*pt)10例5-1,通过指针变量访问整型变量 11指针的赋值在声明指针的同时进行初始化赋值 数据类型 * 指针名 = 初始地址;int a = 100;int *pt = &a; / 声明并用变量名来初始化指针int array10;int *pt = array; / 声明并用数组名来初始化指针 在声明之后,单独使用赋值语句 指针名 = 地址;int a = 100, x;int *pt;pt = &a; / 把变量 a 的地址赋给指针 pt可以通过指针变量 pt 间接访问变量ax = *pt; / 等价于: x = a;12指针变

8、量和一般变量一样, 对于同一类型,存放在它们之中的值是可以改变的, 也就是说可以改变它们的指向 int a, b, *pt1, *pt2; a = 100; b = 200; pt1 = &a; / 把变量 a 的地址赋给指针 pt1 pt2 = pt1; / 使pt2 与pt1指向同一对象 pt2 = &b; / 把变量 b 的地址赋给指针 pt2 *pt2 = *pt1; / 表示把pt1指向的内容赋给pt2所指的区域pt2bpt1a200100&a100&b&a13对运算符& 和 * 的几点说明:1)如pt1 = &a; ,若&*pt1,则按自右而左方向结合(优先级相同),因此先进行 *

9、pt1运算,就是变量a,再执行&运算,即为变量a的地址。pt2 &*pt1; / 它的作用是将&a赋給pt2,等价于 pt2 = &a; 如果pt2原来指向b,经过重新赋值后,它已不再指向b了。pt2b&apt1a&a&b142)*&a :先进行&a 运算,得a 的地址,再进行* 运算。与a等价3)(*pt)+ 相当于 a+如果没有(),相当于*(pt+)。即先做pt+,再求*。而 pt+ 为后加,故先对pt做*pt 操作,得到a,再使pt加1,这样,pt就不再指向a了四、指针链把一个指针指向另一个指针,从而形成如下所示的指针链多重间接(multiple indirection) 地址2pt2

10、地址1 pt1值变量15指向指针的指针变量必须在名称前面添加额外的间接运算符。例如:int *pt; / pt 是指向int 类型的指针的指针可以使用两次间接运算符,用指向指针的指针来间接地访问目标值。例5-2,通过指向指针的指针变量访问整型变量16五、指针表达式与其它变量一样,指针变量也可用于表达式中。还可以使用关系运算符对指针进行比较。p1 = p2p1 != p2对单独变量的指针进行比较没有意义。指针比较一般用于处理数组或字符串 合法 合法 合法 合法 错!17指针可以进行递增、递减运算p1 = p1 + 1;p1 = p2 + 2;当指针进行递增(减)时,所增加的值为该指针指向的数据类

11、型的“长度”字符char1字节整数int2字节浮点数float4字节长整数long4字节双精度数double8字节18 1)可以把另一个变量的地址赋给指针变量。 2)可以把一个指针变量的值赋给另一个指针变量。 3)可以使用NULL或零值来初始化指针变量。 4)可以在指针变量的前面或后面添加递增或递减运算符。 5)指针变量可以与整数值进行加减运算。 6)当两个指针指向相同数据类型的对象时,可以使用关系运算符对它们进行比较操作。 7)不能把指针变量与常量做乘法运算。 8)两个独立的指针变量不能做加法运算。 9)不能把一个数值赋给地址。(例如,&x=10 是非法的) 指针操作的规则195.2 指针与

12、数组一、指向数组元素的指针通过数组下标所能完成的任何操作都可以通过指针来实现。用指针编写的程序比用数组下标编写的程序执行速度快,但理解起来稍微困难一些。例如:int a10, x;int *pa;pa = &a0; / pa指向数组a的第0个元素 pa=a;x = *pa; / 把a0中的内容复制到变量x中pa = &a2; / pa=a+2;2018161412108642a0a9 pa:a:pa+1:pa+2:20二、通过指针引用数组元素如果pa = &a0; 则也可通过指针访问数组元素ai *(a+i) *(pa+i)pai *(pa+i) 引用一个数组元素的方法:下标法,ai指针法,*

13、(pa+i) 或*(a+i)数组元素的地址是通过它的索引和数据类型的长度(比例因子)来计算的。xi的地址 = 基本地址 + (i 数据类型的比例因子)例5-3,设有一个int 型一维数组a,有10个元素。用三种方法输出各元素。2122使用注意 通过指针访问数组元素必须保证所有间接访问都在合法范围内进行 由运算取得的指针值不能超出数组首元素和末元素的位置ai0* ( p + i )321a0a9 p:a:p+1, a+1:p+2, a+2:p+i, a+i:p+9, a+9:23 p = a;24三、地址算术运算如果p是一个指向数组中某个元素的指针,那么p+将对p进行自增运算,并指向下一个元素;

14、而p=p+i 将对p进行加i的增量运算,使其指向指针p当前指向的元素之后的第i个元素。*p+,自右向左结合,等价于*(p+)。作用是先得到p指向的变量的值(*p),然后再使p+1p。*(p+)与*(+p)作用不同。前者先取*p值,然后使p加1;后者使先使p加1,再取*p值。(*p)+,表示p所指向的元素值加1。*(p-)与*(-p)25指针在一定条件下,可进行比较。例如:两个指针变量p, q指向同一数组, 则, =,=, =等关系运算符都能正常进行。 若p = = q为真, 则表示p, q 指向数组的同一元 素; 若pq 为真, 则表示p所指向的数组元素在q所指向的数组元素之前。两个指针变量在

15、一定条件下, 可进行减法运算。例如:设p, q指向同一数组, 且pq,则p-q+1表示位于p和q指向的元素之间的元素的个数。指针与整数之间不能相互转换,但0是唯一的例外。常量0可以赋值给指针,指针也可以和常量0进行比较。程序中经常用符号常量NULL代替常量0。符号常量NULL定义在标准头文件 中。26有效的指针运算包括:相同类型之间的赋值运算;指针同整数之间的加法或减法运算;指向相同数组中元素的两个指针间的减法或比较运算;将指针赋值为0 (或NULL);指针与0 (或NULL)之间的比较运算。27四、指针使用中的常见错误指针使用灵活,用途广泛,但容易出错。 错误使用主要表现为:读出操作,导致得

16、到无效的数据。 这是因为:一个指针在定义后而被赋值之前,其值是未知的。写入操作,导致重写其他数据甚至代码段,这种错误的影响有时不会立即表现出来。使用指针的最常见错误是非法间接访问,例如: int *p, n = 3; *p = n; / 错!这个语句是个大错误,它可能引起的后果无法预料。28五、多维数组与指针多维数组元素的地址二维数组在内存中是按行存放的int a33=1,2,3, 2,3,4, 3,4,5;543432321a2a1a0a(2000)a+1(2006)a+2(2012)a0(2000)a0+1(2002)a0+2(2004)29表示形式含义a二维数组名,指向第0行首地址a0,

17、 *(a+0), *a第0行第0列元素地址a+1, &a1第1行首地址a+i, &ai第i行首地址a1,*(a+1)第1行第0列元素a10的地址a1+1, *(a+1)+1, &a11第1行第1列元素a11的地址ai+j, *(a+i)+j, &aij第i行第j列元素aij的地址*(a1+1), *(*(a+1)+1), a11第1行第1列元素a11的值*(ai+j), *(*(a+i)+j), aij第i行第j列元素aij的值30例5-4,用指针实现二维数组的输出31指向多维数组元素的指针变量 指向数组元素的指针 计算aij在数组中的相对位置(数组大小为mn)为:i*n+j例5-5,改写例5

18、-4 32指向有m个元素组成的一维数组的指针变量int a3; int array23;int (*p)3; int a3; / p 所指的对象是一个包含3个元素的一维数组,p的值是该一维数组的首地址p = array(*p)2(*p)1(*p)0(*p)数组parray1array0pp+133例5-6,改写例5-434六、指针数组的概念数组中的每个元素均为指针类型数据一维指针数组的定义形式为: 类型名 *数组名数组长度;int *p5;比较适于用来指向若干字符串,是字符串处理更加方便、灵活例如,图书馆查书,书名都是字符串且书名长度不同,若放在一个数组中且对它们进行排序,因此如设计一个二维字

19、符数组,需指定长度,浪费空间。可用指针数组来实现35例5-7,将若干字符串按字母顺序(由小到大)输出将字符串数组作为函数参数(sort函数实现)sort函数的两个参数:string用来接收字符串数组,char *string n 用来接收该字符串数组的大小字符串排序算法(选择排序法)基本思想:在某个位置i,找从该位置到最后一个元素之间最小的元素。找到后,如果这个元素不是位置i,则要把这个最小元素交换到i 位置。i 从1 到倒数第2个元素,重复进行上述选择,就会完成数组中各元素的排序输出一组字符串printf(%s%c, stringi, (i成员名 / - 称为成员选择运算符 (*p).成员名 p-.成员名65二、指向结构数组的指针例5

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论