C语言程序设计指针_第1页
C语言程序设计指针_第2页
C语言程序设计指针_第3页
C语言程序设计指针_第4页
C语言程序设计指针_第5页
已阅读5页,还剩84页未读 继续免费阅读

下载本文档

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

文档简介

1、1会计学C语言程序设计指针语言程序设计指针指针是C语言中的一个重要的概念,也是C语言的一个重要特色。正确而灵活地运用指针: 可以有效地表示复杂的数据结构;可以有效地表示复杂的数据结构; 能方便地使用字符串;能方便地使用字符串; 实现动态分配存储空间;实现动态分配存储空间; 有效而方便地使用数组;有效而方便地使用数组; 在调用函数时使能得到多于一个的值在调用函数时使能得到多于一个的值; ; 能直接处理内存地址等。能直接处理内存地址等。void main()int i, j, k, *i_pointer;scanf(“%d%d”, &i, &j);k=i+j;printf(“%dn

2、”, k);i_pointer=&i;k=*i_pointer;printf(“%dn”, k);2000200420083000地址地址存储单元存储单元变量变量ijki_pointer2000200420083000地址地址存储单元存储单元变量变量ijki_pointer存存放放整整数数值值存放整数存放整数存储单元存储单元的地址的地址 例例例例10101010- - - -1111数据存取访问方式与指针数据存取访问方式与指针963按变量按变量存取方存取方式可称式可称“ 直 接直 接访 问访 问 ”方式方式2000按地址按地址存取方存取方式可称式可称“ 间 接间 接访 问访 问 ”方式

3、方式3指针变量所包含的是内存地址,而该指针变量所包含的是内存地址,而该地址便是另一个变量在内存中的存储位地址便是另一个变量在内存中的存储位置。置。指针就是地址,通过指针可以达到指针就是地址,通过指针可以达到间接存取目标的目的。间接存取目标的目的。要正确区分要正确区分: :指针与指针变量这两个概念!7.2 指针运算符指针运算符“&”和和“*”“& &”:取地址符,其操作数可以是各种类型:取地址符,其操作数可以是各种类型的简单变量、数组元素、结构成员,不能用于的简单变量、数组元素、结构成员,不能用于表达式、常量和寄存器变量,是描述变量地址表达式、常量和寄存器变量,是描述变量

4、地址的工具。属单目运算符。如:的工具。属单目运算符。如:int x; scanf(int x; scanf(“%d%d”, , &x&x ););给出变量的存储单元的地址,作为给出变量的存储单元的地址,作为存放键盘输入数据的指针,将数据存存放键盘输入数据的指针,将数据存入变量入变量x x的存储单元之中的存储单元之中“* *”:指针运算符(或称:指针运算符(或称“间接访问间接访问”运算运算符)。属单目运算符。符)。属单目运算符。 作用:作用: 定义说明指针变量。定义说明指针变量。当指针运算符出现在定义说明语句中时,当指针运算符出现在定义说明语句中时,说明其后的标识符为存放地址的变

5、量,系统说明其后的标识符为存放地址的变量,系统为其分配相应的存储单元。为其分配相应的存储单元。int i, j, k,int i, j, k, *i_pointer*i_pointer; ;“* *”:指针运算符(或称:指针运算符(或称“间接访问间接访问”运算运算符)。属单目运算符。符)。属单目运算符。 作用:作用: 通过其操作数(指针)实现通过其操作数(指针)实现“间接访问间接访问”存存储单元的数据。储单元的数据。是将指针是将指针i_pointeri_pointer所指的存储单元的内容赋给变量所指的存储单元的内容赋给变量k k,实际上是对变量实际上是对变量i i的间接存取。的间接存取。* *

6、i_pointeri_pointer意为指意为指针变量针变量i_pointeri_pointer所指的变量,相当于变量所指的变量,相当于变量i i代表值。代表值。i_pointer=&i; k =i_pointer=&i; k = *i_pointer*i_pointer; ;* *i_pointeri_pointer可出现在变量可出现在变量i i能出现的任何地方。能出现的任何地方。* *要求其操作数具有指针意义的值要求其操作数具有指针意义的值! !i;k*i_point;k 等价等价只是存取方式不同只是存取方式不同i;k*i_point;k 等价等价只是存取方式不同只是存取方

7、式不同;ik;*i_point)k (等价等价只是存取方式不同只是存取方式不同;ik;*i_point)k (等价等价只是存取方式不同只是存取方式不同7.3 指针变量的定义说明指针变量的定义说明指针必须先定义后引用,在说明中必须指出指针必须先定义后引用,在说明中必须指出它所指向对象的数据类型。一旦说明后,就不它所指向对象的数据类型。一旦说明后,就不能随意指向别的不同类型的变量。能随意指向别的不同类型的变量。一般形式:一般形式:类型标识符类型标识符* *指针说明符,指针说明符,;几种常用定义形式:几种常用定义形式:(对标识符的说明应以(对标识符的说明应以运算符的优先级为依据层层结合分解理解)运算

8、符的优先级为依据层层结合分解理解)int x, *p;int x, *p;P P是指向整型变量的指针是指向整型变量的指针P P是指向整型变量的指针是指向整型变量的指针int *pf( int *pf( 形参说明表列形参说明表列 ););pfpf是函数是函数pfpf是函数是函数pfpf是返回值为指向整型存储单元地是返回值为指向整型存储单元地址的指针函数址的指针函数pfpf是返回值为指向整型存储单元地是返回值为指向整型存储单元地址的指针函数址的指针函数intint(*pfg*pfg)( ( 形参说明表列形参说明表列 ); ); pfgpfg是指针是指针pfgpfg是指针是指针pfgpfg是是指向一

9、指向一返回整型量函数的指针返回整型量函数的指针pfgpfg是是指向一指向一返回整型量函数的指针返回整型量函数的指针pfgpfg是指向函数的指针是指向函数的指针pfgpfg是指向函数的指针是指向函数的指针int *(*pfgi)( int *(*pfgi)( 形参说明表列形参说明表列 ); ); pfgipfgi是指针是指针pfgipfgi是指针是指针pfgipfgi所指函数是返回指针的函数所指函数是返回指针的函数pfgipfgi所指函数是返回指针的函数所指函数是返回指针的函数pfgipfgi是指向函数的指针是指向函数的指针pfgipfgi是指向函数的指针是指向函数的指针pfgipfgi所指函数

10、是返回指向整型量存储单元所指函数是返回指向整型量存储单元地址的函数地址的函数pfgipfgi所指函数是返回指向整型量存储单元所指函数是返回指向整型量存储单元地址的函数地址的函数int int * *a 5 ;a 5 ; a a是数组是数组 a a是指针数组是指针数组 a a数组的数组的5 5个元素用于存储指向整型存储单元的个元素用于存储指向整型存储单元的 地址地址 对标识符的说明应以运算符的优先级为对标识符的说明应以运算符的优先级为依据层层结合分解理解依据层层结合分解理解7.4 指针与数组指针与数组指针与数组两者关系密切,通过指针可方便指针与数组两者关系密切,通过指针可方便地存取数组元素,且质

11、量高,速度快。地存取数组元素,且质量高,速度快。(1)(1)数组的指针表示:数组的指针表示:数组名:数组名:代表该数组存储单元的起始地址,可称为数代表该数组存储单元的起始地址,可称为数组的指针,是地址常量。组的指针,是地址常量。数组元素:数组元素:相当于变量,代表值,有固定的存储单元相当于变量,代表值,有固定的存储单元及相应地址,可通过及相应地址,可通过& &取地址符得到其地址。因此取地址符得到其地址。因此可通过指向数组元素的指针找到所需的元素。且质量可通过指向数组元素的指针找到所需的元素。且质量高,速度快。高,速度快。设设: : int a10,*pa; pa=&a5

12、;int a10,*pa; pa=&a5;papa当前元素当前元素前趋元素前趋元素后继元素后继元素0 1 2 3 4 5 6 7 8 9a0 1 2 3 4 5 6 7 8 9a系统的内部实现:系统的内部实现:pa+i 所指向的地址所指向的地址 = pa + i * (比例因子比例因子) 数组元素所占字节数数组元素所占字节数数组元素所占字节数数组元素所占字节数系统的内部实现:系统的内部实现:pa+i 所指向的地址所指向的地址 = pa + i * (比例因子比例因子) 数组元素所占字节数数组元素所占字节数数组元素所占字节数数组元素所占字节数数组元素所占字节数数组元素所占字节数数组元素所

13、占字节数数组元素所占字节数0 01 12 2i i9 90 01 12 2i i9 9a apapaa0a0a+1a+1pa+1pa+1a1a1a+2a+2pa+2pa+2a2a2a+ia+ipa+ipa+iaiaia+9a+9pa+9pa+9a9a9下标下标下标下标a a数组数组数组数组数组名数组名数组名数组名 指针指针指针指针下标法下标法下标法下标法*(a)*(a)*(a+1)*(a+1)*(a+2)*(a+2)*(a+i)*(a+i)*(a+9)*(a+9)数组名法数组名法数组名法数组名法*(a)*(a)*(a+1)*(a+1)*(a+2)*(a+2)*(a+i)*(a+i)*(a+9)

14、*(a+9)*(a)*(a)*(a+1)*(a+1)*(a+2)*(a+2)*(a+i)*(a+i)*(a+9)*(a+9)数组名法数组名法数组名法数组名法*(pa)*(pa)*(pa+1)*(pa+1)*(pa+ 2)*(pa+ 2)*(pa+ i)*(pa+ i)*(pa+ 9)*(pa+ 9)指针法指针法指针法指针法*(pa)*(pa)*(pa+1)*(pa+1)*(pa+ 2)*(pa+ 2)*(pa+ i)*(pa+ i)*(pa+ 9)*(pa+ 9)*(pa)*(pa)*(pa+1)*(pa+1)*(pa+ 2)*(pa+ 2)*(pa+ i)*(pa+ i)*(pa+ 9)*(

15、pa+ 9)指针法指针法指针法指针法pa0pa0pa1pa1pa2pa2pa ipa ipa 9pa 9指针数组法指针数组法指针数组法指针数组法pa0pa0pa1pa1pa2pa2pa ipa ipa 9pa 9pa0pa0pa1pa1pa2pa2pa ipa ipa 9pa 9指针数组法指针数组法指针数组法指针数组法位序位序位序位序地址地址地址地址位序位序位序位序地址地址地址地址(2) (2) (2) (2) 数组元素的几种表示:设数组元素的几种表示:设数组元素的几种表示:设数组元素的几种表示:设 int a10,pa=a;int a10,pa=a;int a10,pa=a;int a10,

16、pa=a;数组元素的表示(值)数组元素的表示(值)数组元素的表示(值)数组元素的表示(值)数组元素的表示(值)数组元素的表示(值)数组元素的表示(值)数组元素的表示(值)void main()static int a10=1,2,3,4,5,6,7,8,9,10;int i,*p;for(i=0; i10; i+)printf(“%dn”, ai);/下标法下标法for(i=0; i10; i+)printf(“%dn”, *(a+i);/数组名(地址常量)法数组名(地址常量)法for(p=a; pa+10; p+)printf(“%dn”, *p); /指针变量法指针变量法 下标法和数组名法

17、执行效果相同,下标法和数组名法执行效果相同,C C编译程序将编译程序将aiai转换为转换为*(*(a+i)a+i)处理,即先计算元素地址,然后存处理,即先计算元素地址,然后存取,较费时;取,较费时; 例例例例7 7 7 7- - - -2222运算运算运算运算中数组元素的中数组元素的中数组元素的中数组元素的表示方式的优表示方式的优表示方式的优表示方式的优劣比较。劣比较。劣比较。劣比较。void main()static int a10=1,2,3,4,5,6,7,8,9,10;int i,*p;for(i=0; i10; i+)printf(“%dn”, ai);/下标法下标法for(i=0;

18、 i10; i+)printf(“%dn”, *(a+i);/数组名(地址常量)法数组名(地址常量)法for(p=a; pa+10; p+)printf(“%dn”, *p); /指针变量法指针变量法 指针变量法比前两种方法快,用指针直接指向元素指针变量法比前两种方法快,用指针直接指向元素,不必每次都重新计算地址。有规律的改变地址值(,不必每次都重新计算地址。有规律的改变地址值(p+p+)能大大提高执行效率;能大大提高执行效率; 例例例例7 7 7 7- - - -2222运算运算运算运算中数组元素的中数组元素的中数组元素的中数组元素的表示方式的优表示方式的优表示方式的优表示方式的优劣比较。劣

19、比较。劣比较。劣比较。void main()static int a10=1,2,3,4,5,6,7,8,9,10;int i,*p;for(i=0; i10; i+)printf(“%dn”, ai);/下标法下标法for(i=0; i10; i+)printf(“%dn”, *(a+i);/数组名(地址常量)法数组名(地址常量)法for(p=a; pa+10; p+)printf(“%dn”, *p); /指针变量法指针变量法 下标法较直观,下标法较直观,a5a5即为第即为第6 6个元素,数组名法和个元素,数组名法和指针变量法不直观,不易判断当前处理的元素位置,指针变量法不直观,不易判断当

20、前处理的元素位置,出错处理较复杂,需要采用数据跟踪查错。出错处理较复杂,需要采用数据跟踪查错。 例例例例7 7 7 7- - - -2222运算运算运算运算中数组元素的中数组元素的中数组元素的中数组元素的表示方式的优表示方式的优表示方式的优表示方式的优劣比较。劣比较。劣比较。劣比较。void main()static int a10=1,2,3,4,5,6,7,8,9,10;int i,*p;for(i=0; i10; i+)printf(“%dn”, ai);/下标法下标法for(i=0; i10; i+)printf(“%dn”, *(a+i);/数组名(地址常量)法数组名(地址常量)法f

21、or(p=a; p=0; p&a0=0; p-) )printf(%4d,*p);printf(%4d,*p);printf(printf( nOK!nOK! n);n); 可以使用多种不同的可以使用多种不同的方式来引用一个数组方式来引用一个数组元素。数组名是地址元素。数组名是地址常量,指针是变量,常量,指针是变量,应随时注意其值(地应随时注意其值(地址)的变化。址)的变化。运行结果:运行结果:104 103 102 101 100104 103 102 101 100OK!OK! 特别说明:+和和运算符用于指针变量十分有运算符用于指针变量十分有效,可以使指针变量自动向前或向后移动,指

22、效,可以使指针变量自动向前或向后移动,指向下一个或上一个数组元素。向下一个或上一个数组元素。papaiapapaiapapaiapapaia *)(*)(*)(*)(*等等价价等等价价等等价价等等价价表达式运算过程应从运算符与操作数的结合表达式运算过程应从运算符与操作数的结合和运算次序两个方面去理解:和运算次序两个方面去理解:* *pa+pa+ 首先根据运算符的优先级与操作数结合首先根据运算符的优先级与操作数结合 pa+pa+papa首先与首先与+结合,确定结合,确定+的操作数是的操作数是papa; *pa*pa* *与与papa结合间接存取结合间接存取papa所指存储单元的值。所指存储单元的

23、值。 然后按运算规则分步逐一运算然后按运算规则分步逐一运算 *pa*pa首先间接存取首先间接存取papa所指存储单元的值;所指存储单元的值; pa+pa+然后然后pa+pa+,即即papa指向下一个元素,因为指向下一个元素,因为+在在papa的右边的右边所以所以* *pa+pa+与与*(*(pa+)pa+)等价。等价。同理:ai+ai+也应从运算符与操作数的结合和运算次也应从运算符与操作数的结合和运算次序两个方面去理解序两个方面去理解, ,因为因为+在操作数在操作数i i的右边,所以先的右边,所以先存取存取aiai的值,然后再的值,然后再i+i+。数组名数组名a a代表数组的起始地址,是常量:

24、代表数组的起始地址,是常量:a=pa; a+;a=pa; a+;/都为非法操作都为非法操作;papa是指针变量:是指针变量:pa=a; pa+;pa=a; pa+;/都为有意义的操作。都为有意义的操作。7. 5 数组名,指针和函数参数数组名,指针和函数参数采用数组名和指针作为函数的参数,可通过采用数组名和指针作为函数的参数,可通过传地址方式,实现形参和实参共享存储单元,传地址方式,实现形参和实参共享存储单元,达到数据互相传递的目的,主要有四种组合形达到数据互相传递的目的,主要有四种组合形式:式: 形参和实参都用数组名形参和实参都用数组名 实参用数组名,形参用指针变量实参用数组名,形参用指针变量

25、 实参和形参都用指针变量实参和形参都用指针变量 实参为指针变量,形参为数组名实参为指针变量,形参为数组名(1) (1) (1) (1) 形参和实参都用数组名形参和实参都用数组名形参和实参都用数组名形参和实参都用数组名fun(int x, int n )fun(int x, int n ) main( ) main( ) int a10;int a10;fun( a, 10 );fun( a, 10 ); 说明:说明: 定义数组时必须定义数组时必须说明大小。说明大小。 数组元素的个数数组元素的个数n n的传递是需要的,的传递是需要的,以便正确控制元素以便正确控制元素的访问区域,有效的访问区域,有

26、效防止数组的越界使防止数组的越界使用。用。传值传值 传地址传地址(2) (2) (2) (2) 实参和形参都用指针变量实参和形参都用指针变量实参和形参都用指针变量实参和形参都用指针变量fun(int *x, int n )fun(int *x, int n ) main( ) main( ) int a10int a10,*p;*p;p=a;p=a;fun( p, 10 );fun( p, 10 ); 形参数组以指形参数组以指针形式定义,用针形式定义,用指针实现对数组指针实现对数组元素的操作,定元素的操作,定义简单,不是很义简单,不是很直观,但有时效直观,但有时效率较高。率较高。传值传值 传地

27、址传地址(2) (2) (2) (2) 实参和形参都用指针变量实参和形参都用指针变量实参和形参都用指针变量实参和形参都用指针变量fun(int *x, int n )fun(int *x, int n ) main( ) main( ) int a10int a10,*p;*p;p=a;p=a;fun( p, 10 );fun( p, 10 ); 实参指针变量实参指针变量p p必必须有确定的地址,即须有确定的地址,即必须事先指向一个可必须事先指向一个可使用的存储空间,即使用的存储空间,即语句语句p=a;p=a;是必须的。是必须的。否则,可能由于局部否则,可能由于局部变量的初值的不确定变量的初值

28、的不确定性,导致用户程序对性,导致用户程序对重要数据区或系统文重要数据区或系统文件的读写,造成严重件的读写,造成严重的不可预料的后果。的不可预料的后果。传值传值 传地址传地址(3) (3) (3) (3) 实参用数组名,形参用指针变量实参用数组名,形参用指针变量实参用数组名,形参用指针变量实参用数组名,形参用指针变量fun(int *x, int n )fun(int *x, int n ) main( ) main( ) int a10;int a10;fun( a, 10 );fun( a, 10 ); 形参以指针形形参以指针形式表示,不是很直式表示,不是很直观,使用时应该搞观,使用时应该

29、搞清楚形参和实参的清楚形参和实参的对应关系。对应关系。传值传值 传地址传地址(4) (4) (4) (4) 实参和形参都用指针变量实参和形参都用指针变量实参和形参都用指针变量实参和形参都用指针变量fun(int x,int n )fun(int x,int n ) main( ) main( ) int a10int a10,*p;*p;p=a;p=a;fun( p, 10 );fun( p, 10 ); 实参指针变量实参指针变量p p必须有确定的地址必须有确定的地址。其所指的存储空。其所指的存储空间,可由静态数据间,可由静态数据结构获得,也可由结构获得,也可由动态申请存储空间动态申请存储空间

30、获得。获得。传值传值 传地址传地址7. 6 动态申请存储空间简介动态申请存储空间简介向量点乘示例说明向量点乘示例说明10ibianbnani 。求求,设设有有#include #include #include #include float product(float *a,float *b,int n)float product(float *a,float *b,int n)int i; float s;int i; float s;for(i=0,s=0;in;i+)for(i=0,s=0;in;i+)s=s+(*a+ * *b+);s=s+(*a+ * *b+);return(s);r

31、eturn(s);/向量点乘功能模块向量点乘功能模块void main()void main()float *d1,*d2,s1; int i;float *d1,*d2,s1; int i;d1=(float *)malloc(4 * sizeof(float);d1=(float *)malloc(4 * sizeof(float);d2=(float *)malloc(4 * sizeof(float);d2=(float *)malloc(4 * sizeof(float);for(i=0; i3; i+) for(i=0; i3; i+) scanf(%f%f,d1+,d2+);sc

32、anf(%f%f,d1+,d2+);d1=d1d1=d1- -3;3;d2=d2d2=d2- -3;3;/ /指针复位指针复位s1=product( d1, d2, 3);s1=product( d1, d2, 3);printf(printf( ns1=%fns1=%f n,s1);n,s1); 分解演示说明分解演示说明d1=(float *)malloc(4 * sizeof(float);d1=(float *)malloc(4 * sizeof(float);MemoryMemory- -allocalloc:动态存储动态存储分配函数,它分配后面括号分配函数,它分配后面括号内指定字节数

33、的存储区,并内指定字节数的存储区,并返回返回void/charvoid/char类型的指针,类型的指针,即所分配内存区的首地址,即所分配内存区的首地址,若动态申请空间失败,则返若动态申请空间失败,则返回回NULL(0)NULL(0)。MemoryMemory- -allocalloc:动态存储动态存储分配函数,它分配后面括号分配函数,它分配后面括号内指定字节数的存储区,并内指定字节数的存储区,并返回返回void/charvoid/char类型的指针,类型的指针,即所分配内存区的首地址,即所分配内存区的首地址,若动态申请空间失败,则返若动态申请空间失败,则返回回NULL(0)NULL(0)。申请

34、所需存储空间的申请所需存储空间的大小,字节为单位。大小,字节为单位。申请所需存储空间的申请所需存储空间的大小,字节为单位。大小,字节为单位。强制类型转换:强制类型转换:由于返回的存储区由于返回的存储区首地址是首地址是void/charvoid/char类型的指针,若要类型的指针,若要适用于存放特定类适用于存放特定类型的数据,则必须型的数据,则必须作强制类型的转换作强制类型的转换,使适合存储相应,使适合存储相应数据类型的数据,数据类型的数据,及以相应类型字长及以相应类型字长计算地址。计算地址。强制类型转换:强制类型转换:由于返回的存储区由于返回的存储区首地址是首地址是void/charvoid/

35、char类型的指针,若要类型的指针,若要适用于存放特定类适用于存放特定类型的数据,则必须型的数据,则必须作强制类型的转换作强制类型的转换,使适合存储相应,使适合存储相应数据类型的数据,数据类型的数据,及以相应类型字长及以相应类型字长计算地址。计算地址。float product(float *a, float *b, int n)int i; float s;for(i=0,s=0; in; i+) s=s+(*a+ * *b+);return(s); void main()float *d1, *d2, s1; int i;d1=(float *)malloc(4 * sizeof(floa

36、t);d2=(float *)malloc(4 * sizeof(float);for(i=0; i3; i+) scanf(%f%f, d1+, d2+);d1=d1-3; d2=d2-3;s1=product( d1, d2, 3);printf(ns1=%fn, s1);运行结果:运行结果:s1=14.000000s1=14.000000输入数据输入数据: 1 11 1 2 2 2 2 3 3 3 37.7 多维数组与指针多维数组与指针地址的计算与表示地址的计算与表示: :以三维数组的元素为例,若设以三维数组的元素为例,若设int int b345b345;则其元素则其元素bijkbij

37、k各部分可分解表示各部分可分解表示为:为:bijbijbibib b元素(数值)元素(数值)元素(数值)元素(数值)一维数组名一维数组名( (地址地址) ) 列列一维数组名一维数组名( (地址地址) ) 列列二维数组名二维数组名( (地址地址) ) 行行二维数组名二维数组名( (地址地址) ) 行行三维数组名三维数组名( (地址地址) ) 层层三维数组名三维数组名( (地址地址) ) 层层bijkbijk含义含义单位单位( (地址地址) )bijkbijk含义含义单位单位( (地址地址) )数组名代表的维数组名代表的维数不同,计算的地数不同,计算的地址单位也就不同,址单位也就不同,要以层、行和

38、列的要以层、行和列的观点理解地址的表观点理解地址的表示方式。示方式。以二维数组为例说明:以二维数组为例说明:int a34, *p; p = *a;a,a0,pa,a0,pa,a0,pa,a0,p2044 2044 122040 2040 112036 2036 102032 2032 92028 2028 82024202472020202062016 2016 52012 2012 42008200832004200422000200012044 2044 122040 2040 112036 2036 102032 2032 92028 2028 82024202472020202062

39、016 2016 52012 2012 4200820083200420042200020001a+1,a1a+1,a1a+1,a1a+1,a1a+2,a2a+2,a2a+2,a2a+2,a2a0+1,p+1a0+1,p+1a0+1,p+1a0+1,p+12000 1a002004 2a012008 3a022012 4a032016 5a102020 6a112024 7a122028 8a132032 9a202036 10a212040 11a222044 12a232000 1a002004 2a012008 3a022012 4a032016 5a102020 6a112024 7a

40、122028 8a132032 9a202036 10a212040 11a222044 12a23a,a0,pa,a0,pa,a0,pa,a0,pa0+1,p+1a0+1,p+1a0+1,p+1a0+1,p+1a+1,a1a+1,a1a+1,a1a+1,a1a+2,a2a+2,a2a+2,a2a+2,a2a1+2,p+6a1+2,p+6a1+2,p+6a1+2,p+6外部逻辑形态:地址的单位不外部逻辑形态:地址的单位不同,指针运算的走向不同。同,指针运算的走向不同。内部一维存储空间根据地址单位内部一维存储空间根据地址单位的不同,指针运算的走向形态。的不同,指针运算的走向形态。内存中的表示内存

41、中的表示以二维数组为例说明:以二维数组为例说明:int a34, *p; p = *a;2000 1a002004 2a012008 3a022012 4a032016 5a102020 6a112024 7a122028 8a132032 9a202036 10a212040 11a222044 12a232000 1a002004 2a012008 3a022012 4a032016 5a102020 6a112024 7a122028 8a132032 9a202036 10a212040 11a222044 12a23a,a0,pa,a0,pa,a0,pa,a0,pa0+1,p+1a0

42、+1,p+1a0+1,p+1a0+1,p+1a+1,a1a+1,a1a+1,a1a+1,a1a+2,a2a+2,a2a+2,a2a+2,a2a1+2,p+6a1+2,p+6a1+2,p+6a1+2,p+6内部一维存储空间根据地址单位内部一维存储空间根据地址单位的不同,指针运算的走向形态。的不同,指针运算的走向形态。 p = *a;p = *a;指针赋值时赋指针赋值时赋值运算符的两边的地址单值运算符的两边的地址单位应一致;位应一致; a+1a+1 相当于以一维数组相当于以一维数组为存储单位(行)为存储单位(行)+1+1,表,表示下一行地址;示下一行地址;说明说明: :以二维数组为例说明:以二维数

43、组为例说明:int a34, *p; p = *a;2000 1a002004 2a012008 3a022012 4a032016 5a102020 6a112024 7a122028 8a132032 9a202036 10a212040 11a222044 12a232000 1a002004 2a012008 3a022012 4a032016 5a102020 6a112024 7a122028 8a132032 9a202036 10a212040 11a222044 12a23a,a0,pa,a0,pa,a0,pa,a0,pa0+1,p+1a0+1,p+1a0+1,p+1a0+1

44、,p+1a+1,a1a+1,a1a+1,a1a+1,a1a+2,a2a+2,a2a+2,a2a+2,a2a1+2,p+6a1+2,p+6a1+2,p+6a1+2,p+6内部一维存储空间根据地址单位内部一维存储空间根据地址单位的不同,指针运算的走向形态。的不同,指针运算的走向形态。 a0a0 一维数组名单位一维数组名单位列,列,a0+1a0+1相当于以一个相当于以一个元素为存储单位元素为存储单位+1+1,表示,表示下一列地址;下一列地址; p p 是指向整型存储单是指向整型存储单元的指针,相当于以元素元的指针,相当于以元素为单位,故为单位,故p+1p+1就是下移就是下移一个元素位置。一个元素位置

45、。以二维数组为例说明:以二维数组为例说明:int a34, *p; p = *a;2000 1a002004 2a012008 3a022012 4a032016 5a102020 6a112024 7a122028 8a132032 9a202036 10a212040 11a222044 12a232000 1a002004 2a012008 3a022012 4a032016 5a102020 6a112024 7a122028 8a132032 9a202036 10a212040 11a222044 12a23a,a0,pa,a0,pa,a0,pa,a0,pa0+1,p+1a0+1,

46、p+1a0+1,p+1a0+1,p+1a+1,a1a+1,a1a+1,a1a+1,a1a+2,a2a+2,a2a+2,a2a+2,a2a1+2,p+6a1+2,p+6a1+2,p+6a1+2,p+6内部一维存储空间根据地址单位内部一维存储空间根据地址单位的不同,指针运算的走向形态。的不同,指针运算的走向形态。若 要 通 过若 要 通 过p p 访 问访 问aIjaIj则应表示为以下形则应表示为以下形式:式:以行和列的观点解释多维数组的概念,以行和列的观点解释多维数组的概念,当数组为三维时,可在行和列的基础上当数组为三维时,可在行和列的基础上增加层或页的概念,因此不难理解指针增加层或页的概念,因

47、此不难理解指针的计算及不同情况下的计算公式(根据的计算及不同情况下的计算公式(根据定义的指针数据结构与所给的初始地址定义的指针数据结构与所给的初始地址不同情况(层、行、列)而确定)。不同情况(层、行、列)而确定)。不同维数的数组名所代表的地址的单位不同,不同维数的数组名所代表的地址的单位不同,其存取元素的方式也不同。其存取元素的方式也不同。若以二维数组名对其下属元素进行存取,需若以二维数组名对其下属元素进行存取,需二次间址访问;二次间址访问;列列地地址址行行地地址址转转换换 相相应应存存储储单单元元的的内内容容列列地地址址间间址址访访问问 行转换为列行转换为列以列为单位计算地址以列为单位计算地

48、址间址访问间址访问12)1)2(aa存存取取的的元元素素为为 行转换为列行转换为列行转换为列行转换为列以列为单位计算地址以列为单位计算地址以列为单位计算地址以列为单位计算地址间址访问间址访问间址访问间址访问12)1)2(aa存存取取的的元元素素为为 不同维数的数组名所代表的地址的单位不同,不同维数的数组名所代表的地址的单位不同,其存取元素的方式也不同。其存取元素的方式也不同。若以一维数组名对其下属进行存取,一次间若以一维数组名对其下属进行存取,一次间址访问即可:址访问即可:以列为单位计算地址以列为单位计算地址以列为单位计算地址以列为单位计算地址间址访问间址访问间址访问间址访问20)20aa存存

49、取取的的元元素素为为(值值)相相应应存存储储单单元元的的内内容容(列列地地址址间间址址访访问问 指针变量作形参以接受通过实参数组名传递来的地指针变量作形参以接受通过实参数组名传递来的地址,有两种方法:址,有两种方法: 用指向元素的指针变量(单位列);用指向元素的指针变量(单位列); 用指向一维数组的指针变量(单位行)。用指向一维数组的指针变量(单位行)。不同维数的数组名所代表的地址的单位不同,不同维数的数组名所代表的地址的单位不同,其存取元素的方式也不同。其存取元素的方式也不同。关键是形实结合时对应的地址计算单位应匹配一致!void average(float *p, int n)float

50、*p_end, aver, sum=0;for(p_end=p+n-1; p=p_end; p+) sum=sum+(*p);aver=sum/n; printf(average=%5.2fn,aver);void search(float (*p)4, int n)int i;for(i=0; i4; i+) printf(%5.2f , *(*(p+n)+i);void main()static float score34=65, 67, 70, 60,80, 87, 90, 81,90, 99, 100, 98;average( *score, 12 ); search( score,

51、2 ); 例例7 7- -4 4 有一个班,有一个班,3 3个学生,各学个学生,各学4 4门课程,计算总平均分及打印门课程,计算总平均分及打印第第3 3名学生的成绩。名学生的成绩。行转换为列行转换为列 行行地地址址 average=82.25average=82.2590.00 99.00 100.00 98.0090.00 99.00 100.00 98.007.8 字符数组和指针字符数组和指针 例例7 7- -5 5 一个具有文字复制和比较功能的程序一个具有文字复制和比较功能的程序#include #include void main()void main()static char s11

52、3=I love USTC!;static char s113=I love USTC!;char s313, *s2=I love USTC;char s313, *s2=I love USTC;void u_strcpy( char *s, char *t );void u_strcpy( char *s, char *t );int u_strcmp( char *s, char *t );int u_strcmp( char *s, char *t );u_strcpy( s3, s1 );u_strcpy( s3, s1 );printf(%s %dprintf(%s %d n,s3

53、,u_strcmp( s1,s2 );n,s3,u_strcmp( s1,s2 ); 字符常数在内存中以字符数组形式存储。字符常数在内存中以字符数组形式存储。static char s113=I love USTC!;static char s113=I love USTC!;char s313, *s2=I love USTC;char s313, *s2=I love USTC;说明说明: :2000I love U US ST TC!02000I love U US ST TC!02013I love U US ST T C 02013I love U US ST T C 0 给字符数组

54、赋初值首先分配存储空间,然给字符数组赋初值首先分配存储空间,然后采用逐个字符复制的形式。后采用逐个字符复制的形式。static char s113=I love USTC!;static char s113=I love USTC!;2000Ilove U US ST TC!02000Ilove U US ST TC!0s10 1 2 3 4 5 6 7 8 9 10 11 12Ilove U US ST TC!0Ilove U US ST TC!0void u_strcpy( char *s, char *t )while(*s = *t) != 0)s+; t+;s1Ilove U US

55、ST TC!00 1 2 3 4 5 6 7 8 9 10 11 12s1Ilove U US ST TC!00 1 2 3 4 5 6 7 8 9 10 11 12s30 1 2 3 4 5 6 7 8 9 10 11 12s30 1 2 3 4 5 6 7 8 9 10 11 12t tmain()u_strcpy( s3, s1 );S Ss3Ilove U US ST TC!0s3Ilove U US ST TC!0int u_strcmp( char *s, char *t )for( ; *s=*t; s+,t+ )if(*s=0) return(0);return(*s-*t);

56、s1Ilove U US ST TC!00 1 2 3 4 5 6 7 8 9 10 11 12s1Ilove U US ST TC!00 1 2 3 4 5 6 7 8 9 10 11 122013Ilove U US ST TC0s220132013Ilove U US ST TC0s22013t2013t2013传递传递s传递s传递main()u_strcmp( s1,s2 )字符数组:字符数组:固定长度且一般需要预定义得大一固定长度且一般需要预定义得大一些,可能浪费内存空间。些,可能浪费内存空间。字符串不但可以用字符数组表示字符串不但可以用字符数组表示, ,也可以用也可以用字符指针变量

57、来表示:字符指针变量来表示:字符指针:字符指针:内存空间可根据字符串实际长度确内存空间可根据字符串实际长度确定,节省内存空间。定,节省内存空间。7.9 指针运算指针运算指针是指向某类型数据存储单元的地址,需指针是指向某类型数据存储单元的地址,需注意以下问题:注意以下问题: 变量、数组的地址分配是由编译程序决定的,因变量、数组的地址分配是由编译程序决定的,因此不能将任意的整数向指针变量赋值;此不能将任意的整数向指针变量赋值; 指针不是整数,但指针的值是具体类型的特定变指针不是整数,但指针的值是具体类型的特定变量地址所允许的整数,因此不能象整型变量那样对指量地址所允许的整数,因此不能象整型变量那样

58、对指针进行所有的算术、逻辑和关系运算。针进行所有的算术、逻辑和关系运算。1)1) 算术运算,设算术运算,设p,qp,q为指针,且指向同类型数据集合,为指针,且指向同类型数据集合,n n为整数,以下为合法且意义为:为整数,以下为合法且意义为: 指针允许实施的运算:指针允许实施的运算:p+np+n:p p指向同类型数据集合的当前位置后的第指向同类型数据集合的当前位置后的第n n个成员。个成员。p p- -n n:p p指向同类型数据集合的当前位置前的第指向同类型数据集合的当前位置前的第n n个成员。个成员。编译程序实施的内部运算分别为:编译程序实施的内部运算分别为:p+n*(p+n*(类型所占字节

59、的长度类型所占字节的长度) )p p- -n*(n*(类型所占字节的长度类型所占字节的长度) )p+p+:当前指针位置后移一个成员,先以当前指针位置后移一个成员,先以p p指针作即时指针作即时操作数,然后自增。操作数,然后自增。-p p:当前指针位置前移一个成员,先自减,然后以自当前指针位置前移一个成员,先自减,然后以自减后的减后的p p作为即时操作数。作为即时操作数。+p p:当前指针位置后移一个成员,先自增,然后以自当前指针位置后移一个成员,先自增,然后以自增后的增后的p p作为即时操作数。作为即时操作数。p p:当前指针位置前移一个成员,先以当前指针位置前移一个成员,先以p p指针作即时

60、指针作即时操作数,然后自减。操作数,然后自减。p p- -q q:其值表示其值表示p,qp,q之间的成员个数,其值为整数,之间的成员个数,其值为整数, 而而不是指针。不是指针。2)2) 关系运算关系运算:(:(前提是指针必须是指向同一类型的数前提是指针必须是指向同一类型的数据)据), ,若若,=,=,等运算符两边的操作数是等运算符两边的操作数是指向同一数据集合(如数组、结构等),就成为有指向同一数据集合(如数组、结构等),就成为有意义的比较。意义的比较。pqpq:表示表示p,qp,q为指向同一数组中的两个不同的元素,为指向同一数组中的两个不同的元素,它表明如果它表明如果p p所指向的元素在所指向的元素在q q所指元素之前时表达式所指元素之前时表达式值为值为真真,否则为,否则为假假,如果,如果p,qp

温馨提示

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

评论

0/150

提交评论