




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、第8章 指针2022-1-27C语言程序设计实用教程第8章1第8章 指针2022-1-27C语言程序设计实用教程第8章2 教学提示教学提示 “ “指针指针”是是C C语言中广泛使用的一种数据类型,运用指针编语言中广泛使用的一种数据类型,运用指针编程是程是C C语言最主要的风格之一。利用指针变量可以表示各种语言最主要的风格之一。利用指针变量可以表示各种数据结构,实现动态内存分配,不但能很方便地使用数组数据结构,实现动态内存分配,不但能很方便地使用数组和字符串,还能像汇编语言一样处理内存地址,从而编出和字符串,还能像汇编语言一样处理内存地址,从而编出精练而高效的程序。但是,由于指针概念较复杂,使用
2、较精练而高效的程序。但是,由于指针概念较复杂,使用较灵活,初学者常常感到较难理解,因此,学习时必须从指灵活,初学者常常感到较难理解,因此,学习时必须从指针的概念入手,正确理解指针及指针在数组和函数方面的针的概念入手,正确理解指针及指针在数组和函数方面的应用。应用。 教学目标教学目标 要求学生掌握指针的概念和运算规则,掌握用指针访问变量、要求学生掌握指针的概念和运算规则,掌握用指针访问变量、一维数组和二维数组的方法,以及用指针处理字符串的方一维数组和二维数组的方法,以及用指针处理字符串的方法。通过多编程、多上机调试程序来体会指针的概念及其法。通过多编程、多上机调试程序来体会指针的概念及其使用的规
3、律,并应用于实际的编程中。使用的规律,并应用于实际的编程中。第8章 指针2022-1-27C语言程序设计实用教程第8章31.1.内存与内存地址内存与内存地址v 内存地址:内存地址:内存是计算机用于存储数据的存储器,以一个字节作为存储单元,为了便于访问,给每个字节单元一个唯一的编号,第一字节单元编号为0,以后各单元按顺序连续编号,这些单元编号称为内存单元的地址 。 变量地址:变量地址:变量所分配存储空间的首字节单元地址(字节单元编号)。 第8章 指针2022-1-27C语言程序设计实用教程第8章42、变量、变量名、变量的地址、变量值、变量、变量名、变量的地址、变量值 每个变量都通过变量名与相应的
4、存储单元相连系,具体分配哪些单元给变量,由编译系统完成变量名到对应内存单元地址的变换。 变量分配存储空间的大小由类型决定。 变量的值则是指相应存储单元的内容。 第8章 指针2022-1-27C语言程序设计实用教程第8章53、指针、变量的指针和指针变量、指针、变量的指针和指针变量 指针:就是 “内存单元的地址”。指针指向一个内存单元。变量的指针:就是“变量的地址”。变量的指针指向一个变量对应的内存单元。指针变量:就是地址变量。地址(指针)也是数据,可以保存在一个变量中。保存地址(指针)数据的变量称为指针变量。第8章 指针2022-1-27C语言程序设计实用教程第8章6系统为特殊变量系统为特殊变量
5、p p(用来存放地址的)分配的存储空间地址是(用来存放地址的)分配的存储空间地址是48004800,p p中保存的是变量中保存的是变量a a的地址的地址, ,即即40004000,当要读取,当要读取a a变量的值变量的值1234512345时,不是直接通过时,不是直接通过a a变量变量, ,也不是直接通过保存也不是直接通过保存1234512345的内的内存单元的地址存单元的地址40004000去取值,而是先通过变量去取值,而是先通过变量p p得到得到p p的值的值40004000,即即a a的地址,再根据地址的地址,再根据地址40004000读取它所指向单元的值读取它所指向单元的值123451
6、2345。 这种间接的通过变量p得到变量a的地址,再存取变量a的值的方式即为“间接存取”。 通常称变量通常称变量p p指向变量指向变量a a,变量,变量a a是变量是变量p p所指向的对象所指向的对象400012345400040024800pap(4800) p(4800) a(4000) 4000123454000间接存取示意图第8章 指针2022-1-27C语言程序设计实用教程第8章74 4、变量值的存取、变量值的存取通过变量在内存中的通过变量在内存中的地址进行存取地址进行存取 系统执行“scanf(”%d“,&a);”和“printf(”a=%dn“, a);”时,存取变量a值
7、的方式可以有两种: 直接访问直接访问直接利用变量的地址进行存取。 1)上例中scanf(“%d”,&a)的执行过程是这样的: 通过变量名a找到变量a的起始地址3000;然后将键盘输入的值(假设为)送到内存单元3000和3001中。此时,变量a在内存中的地址和值,如图8.4所示。第8章 指针2022-1-27C语言程序设计实用教程第8章8间接访问间接访问通过另一变量访问该变量的值。语言规定:在程序中可以定义一种特殊的变量(称为指针变量指针变量),用来存放变量的地址。例如上例定义了这样一个指针变量p,它被分配到4000、4001单元,其值可通过赋值语句“p=a;”得到。此时,指针变量p的值
8、就是变量a在内存中的起始地址3000,如图8.4所示。通过指针变量p存取变量a值的过程如下:第8章 指针2022-1-27C语言程序设计实用教程第8章9pa300034000400130003001第8章 指针2022-1-27C语言程序设计实用教程第8章105.5.指针的概念指针的概念 在语言中,用指针来表示一个变量指向另一个变量这样的指向关系。 所谓指针即地址。 一个变量的指针即该变量的地址,如4000就是指向变量a的指针。 指针变量:专门存放地址的变量,如p即是一个指针变量,它存放的是a的地址4000。第8章 指针2022-1-27C语言程序设计实用教程第8章118.1.2 指针变量的定
9、义与初始化指针变量的定义与初始化1. 1. 指针变量的定义指针变量的定义 基基类型类型 *指针变量名;指针变量名;例:float *p1; (定义p1为指向实型变量的指针变量) char *p2; (定义p2为指向字符型变量的指针变量)在指针变量定义中,*是一个说明符,它表明其后的变量是指针变量,如p是指针变量,而不要认为“*p”是指针变量。指针变量定义时指定的数据类型不是指针变量本身的数据类型,而是指针变量所指向的对象(或称目标)的数据类型 指针变量存放的是所指向的某个变量的地址值,而普通变量保存的是该变量本身的值 指针变量并不固定指向一个变量,可指向同类型的不同变量第8章 指针2022-1
10、-27C语言程序设计实用教程第8章12(1) 指针运算符与地址运算符指针运算符与地址运算符 与指针引用有关的两个运算符:&与* &:取地址运算符 *:指针运算符,或称指向运算符、间接访问运算 符。指针指向的对象的表示形式: *指针变量此处*是访问指针所指对象的运算符,与指针定义时的*不同。2. 指针变量初始化 第8章 指针2022-1-27C语言程序设计实用教程第8章13(2) 指针变量初始化若有定义: int a,*p;语句仅仅定义了指针变量p,但指针变量并未指向确定的变量(或内存单元)。因为这些指针变量还没有赋给确定的地址值,只有将某一具体变量的地址赋给指针变量之后,指针变
11、量才指向确定的变量(内存单元)。指针变量初始化指针变量初始化:在定义指针时同时给指针一个初始值如: int a,*p=&a;40003a(4000)pa*pa第8章 指针2022-1-27C语言程序设计实用教程第8章148.1.3 8.1.3 指针变量的引用指针变量的引用与指针引用有关的两个运算符:与指针引用有关的两个运算符:(1)&:取地址运算符取地址运算符(2)*:指针运算符(或称间接访问运算符:指针运算符(或称间接访问运算符)第8章 指针2022-1-27C语言程序设计实用教程第8章15有定义:有定义: int a,int a,* *p=&a;p=&a;用
12、用* *p p来表示来表示p p指向的对象指向的对象a,a,* *p p与与a a是等价的。是等价的。 * *p p可以象普通变量一样使用。可以象普通变量一样使用。 例如:例如: a=12;a=12; * *p=12;p=12; scanf(%d,& scanf(%d,&* *p); scanf(%d,p);p); scanf(%d,p); printf(“%d%d”, printf(“%d%d”,* *p,a);p,a);注意注意:* *与与& &具有相同的优先级,具有相同的优先级,结合方向从右到左结合方向从右到左。这样,。这样,& &* *p
13、 p即即&(&(* *p),p),是对变量是对变量* *p p取地址,它与取地址,它与&a&a等价;等价;p p与与&(&(* *p)p)等价,等价,a a与与* *(&a)(&a)等价。等价。 第8章 指针2022-1-27C语言程序设计实用教程第8章168.1.4 指针运算指针运算1. 1. 指针的赋值运算指针的赋值运算(1)将变量地址值赋给指针变量,使指针指向该变量。设有如下定义: int a,b,*pa,*pb; float *pf;第一行定义了整型变量a,b及指针变量pa,pb。pa、pb还没有被赋值,因此pa、pb没有
14、指向任何变量, 下面语句完成对pa,pb的赋值: pa=&a; pb=&b;第8章 指针2022-1-27C语言程序设计实用教程第8章17例如:int j,k; int *pointer1,*pointer2; pointer1=&j;pointer2=&k; pointer1jpointer2k第8章 指针2022-1-27C语言程序设计实用教程第8章18(2) 相同类型的指针变量间的赋值相同类型的指针变量间的赋值 pa与pb都是整型指针变量,它们间可以相互赋值,如:pb=pa; 即 pa,pb都指向变量a,此时a、*pa、*pb是等价的。指针指向变化如下图:
15、注意注意:只有相同类型的指针变量才能相互赋值,如pf=pa;是不允许的。因为pa是整型指针,pf是浮点型指针。&a&bpapba,*pab,*pb&a&apapba,*pa,*pbb第8章 指针2022-1-27C语言程序设计实用教程第8章19()给指针变量赋()给指针变量赋空值空值 给指针变量赋空值,说明该指针不指向任何变量。 “空”指针值用NULL表示,NULL是在头文件stdio.h中预定义的常量,其值为,在使用时应加上预定义行,如: #include stdio.h int *pa=NULL; 亦可以用下面的语句给指针赋“空值”: pa=0; 或: pa
16、=0; 这里指针pa并非指向0地址单元,而是具有一个确定的“空值”,表示pa不指向任何变量。注意注意:指针虽然可以赋值指针虽然可以赋值0 0,但却不能把其它的常量地址赋给,但却不能把其它的常量地址赋给指针。例如:指针。例如: pa=4000; pa=4000; 是非法的。是非法的。第8章 指针2022-1-27C语言程序设计实用教程第8章20例例 8.1 指针定义与初始化指针定义与初始化main()int a,b;int *pointer_1,*pointer_2;a=100;b=10;pointer_1=&a; pointer_2=&b; printf (%d,%dn,a,b
17、);printf(%d,%dn,*pointer_1,*pointer_2); 第8章 指针2022-1-27C语言程序设计实用教程第8章21程序运行结果:100,10100,10&a&bbPointer_1Pointer_2a*pointer_1*pointer_2第8章 指针2022-1-27C语言程序设计实用教程第8章22例例8.2 8.2 从键盘上输入两个整数到从键盘上输入两个整数到a a、b, b,按由大到小输出。按由大到小输出。#include main( ) int a,b,*pa=&a,*pb=&b,*p;/*定义指针变量定义指针变量pa、pb,
18、如下页图如下页图a*/ scanf(%d%d,&a,&b); if (*pa*pb) p=pa; /*进行指针交换进行指针交换,如下页图如下页图b,c*/ pa=pb; pb=p; printf(n a=%d,b=%dn,a,b); printf(n max=%d,min=%d,*pa,*pb); /* pa指向大数,指向大数,pb指向小数指向小数*/第8章 指针2022-1-27C语言程序设计实用教程第8章23若输入: 12 22输出结果: a=12,b=22 max=22,min=12 (b) (c)指针变化示意图1222ppapb1222ppapbpapbab第8章 指针
19、2022-1-27C语言程序设计实用教程第8章242. 2. 指针的算术运算指针的算术运算 (1) 加减运算: 一个指针可以加、减一个整数n,其结果与指针所指对象的数据类型有关。指针变量的值应增加或减少“nsizeof(指针类型)”。 加减运算常用于数组的处理加减运算常用于数组的处理。对指向一般数据的指针,加减运算无实际意义。例如: int a10,*p=a,*x; x=p+3; /*实际上是p加上3*2个字节赋给x, x指向数组的第三个分量*/ 对于不同基类型的指针,指针变量“加上”或“减去”一个整数n所移动的字节数是不同的。例如: float a10, *p=a, *x; p=p+3; /
20、*实际上是p加上3*4个字节赋给x, x依然指向数组的第三个分量*/ 第8章 指针2022-1-27C语言程序设计实用教程第8章25 (2) 自增自减运算指针变量自增、自减运算具有上述运算的特点,但有前置后置、先用后用的考虑,务请小心。 例如: int a10, *p=a, *x; x=p+; /* x第一个元素分量, p指向第二个元素*/ x=+p; /* x、 p均指向数组的第二个分量*/* p+相当于*(p+ +)。*(p+)与(*p)+ 含义不同,前者表示地址自增地址自增,后者表示当前当前所指向的数据自增所指向的数据自增。 第8章 指针2022-1-27C语言程序设计实用教程第8章26
21、2. *&a的含意是什么? (答:a )3. (*p)+相当于什么? (答:a+ )思考:1.若有定义 int a,*p; 执行了“p=&a”,则: “&*p”的含意是什么?(答:相当于&a )第8章 指针2022-1-27C语言程序设计实用教程第8章27 3. 3.指针的关系运算指针的关系运算 与基本类型变量一样,指针可以进行关系运算。与基本类型变量一样,指针可以进行关系运算。在关系表达式中允许对两个指针进行所有的关系运算。若在关系表达式中允许对两个指针进行所有的关系运算。若p,q是两个同类型的指针变量,则:是两个同类型的指针变量,则:pq,p=q都都是允许的
22、。是允许的。 指针的关系运算在指向数组的指针中广泛的运用,假设指针的关系运算在指向数组的指针中广泛的运用,假设 p、q是指向同一数组的两个指针,执行是指向同一数组的两个指针,执行pq的运算,其含义为,的运算,其含义为,若表达式结果为真(非值),则说明若表达式结果为真(非值),则说明p所指元素在所指元素在q所指元素所指元素之后。或者说之后。或者说q所指元素离数组第一个元素更近些。所指元素离数组第一个元素更近些。 注意:在指针进行关系运算之前,指针必须指向确定的变量注意:在指针进行关系运算之前,指针必须指向确定的变量或存储区域,即指针有初始值;另外,只有相同类型的指针才或存储区域,即指针有初始值;
23、另外,只有相同类型的指针才能进行比较。能进行比较。 第8章 指针2022-1-27C语言程序设计实用教程第8章288.2 8.2 指向数组的指针指向数组的指针 数组名代表了数组的首地址(即第一数组名代表了数组的首地址(即第一个数组元素的地址)。根据指针的概念,个数组元素的地址)。根据指针的概念,数组的指针是指数组在内存中的起始地址,数组的指针是指数组在内存中的起始地址,而数组元素的指针是指数组元素在内存中而数组元素的指针是指数组元素在内存中的地址。由于数组的各元素在内存中是连的地址。由于数组的各元素在内存中是连续存放的,所以利用指向数组或数组元素续存放的,所以利用指向数组或数组元素的指针变量来
24、使用数组,将更加灵活、快的指针变量来使用数组,将更加灵活、快捷。捷。第8章 指针2022-1-27C语言程序设计实用教程第8章298.2.1 指向一维数组的指针指向一维数组的指针数组名是一个常量指针,它的值为该数组的首地址 1.指向数组的指针的定义方法与指向基本类型变量的指指向数组的指针的定义方法与指向基本类型变量的指针的定义方法相同针的定义方法相同,例如:int a10=1,3,5,7,9,11,13,15,17,19;int *p;p=&a2; (把数组元素a2的地址赋给指针变量p)p=a; (把数组的首地址赋给指针变量p)p=&a0;把a0元素的地址赋给指针变量p。也就是
25、说,p指向a数组的第一个元素。 第8章 指针2022-1-27C语言程序设计实用教程第8章30第8章 指针2022-1-27C语言程序设计实用教程第8章31C语言规定:数组名代表数组首地址,是一个地址常量。因此,下面两个语句等价: p=&a0; p=a;在定义指针变量的同时可赋初值: int a10, *p=&a0; (或 int *p=a;)等价于:int *p; p=&a0; 两句。第8章 指针2022-1-27C语言程序设计实用教程第8章32指向数组的指针变量p&a013151719pa0:a9p9a+0p+1 或 a+1p+9 或 a+9*(a+9) 或
26、*(p+9)第8章 指针2022-1-27C语言程序设计实用教程第8章338.2.2.8.2.2.通过指针引用数组元素通过指针引用数组元素 *p=5;表示对p当前所指的数组元素赋以一个值5。C规定:p+1指向数组的下一元素(而不是将p值简单地加1)。p+1意味着使p的原值(地址)加d个字节(d为一个数组元素所占的字节数)。如果p的初值为&a0,则:(1)p+i和a+i就是ai的地址,或者说它们指向a数组的第i个元素(见下页图)。(2)*(p+i)或*(a+i)是p+i或a+i所指向的数组元素,即ai。(3)指向数组的指针变量也可以带下标,如pi与*(p+i)、 ai等价 。第8章 指针
27、2022-1-27C语言程序设计实用教程第8章34*(p+i)a数组a0a1a2aia9pp+1,a+1p+i, a+ip+9, a+9 综上所述,引用一个数组元素有二法:(1)下标法:如ai形式;(2)指针法:如*(a+i)或 *(p+i)。其中a是数组名,p是指向数组的指针变量,其初值p=a。第8章 指针2022-1-27C语言程序设计实用教程第8章35main()int a10;int i;for (i=0;i10;i+)scanf(%d,&ai);printf(n);for (i=0;i10;i+)printf(%d, ai ) ;例例8.5 8.5 用三种方法输出数组全部元素
28、。用三种方法输出数组全部元素。(1)(1)下标法下标法第8章 指针2022-1-27C语言程序设计实用教程第8章36main()int a10;int i;for (i=0;i10;i+)scanf(%d,&ai);printf(n);for (i=0;i10;i+)printf(%d, *(a+i) );(2)通过数组名计算数组元素地址通过数组名计算数组元素地址,输出元素的值输出元素的值第8章 指针2022-1-27C语言程序设计实用教程第8章37(3)用指针变量指向数组元素main()int a10;int *p,i;for (i=0;i10;i+)scanf(%d,&ai
29、);printf(n);for (p=a;p(a+10);p+)printf(%d, *p ); 三种方法的比较三种方法的比较:用下标法下标法比较直观,能直接知道是第几个元素;而用指针法指针法则执行效率更高。第8章 指针2022-1-27C语言程序设计实用教程第8章38使用指针变量时,应注意:使用指针变量时,应注意:(1)指针变量可实现使本身的值改变。)指针变量可实现使本身的值改变。 P+合法;但合法;但a+不合法(不合法(a是数组名,代表数组首地址,是数组名,代表数组首地址,在程序运行中是固定不变的。)在程序运行中是固定不变的。)(2)要注意指针变量的当前值。)要注意指针变量的当前值。mai
30、n()int a10;int *p, i;p=a;for ( ;pa+10;p+) scanf(%d,p);printf(n);for ( ;p(a+10);p+)printf(%d, *p ); 不能&p增加:p=a;第8章 指针2022-1-27C语言程序设计实用教程第8章39(3 3)* *p+p+相当于相当于* *(p+)(p+),因为,因为* *与与+优先级相同,且结合优先级相同,且结合方向从右向左,其作用是先获得方向从右向左,其作用是先获得p p指向变量的值,然后执指向变量的值,然后执行行p=p+1;p=p+1;(4 4)* *(p+)(p+)与与* *(+p)(+p)意义
31、不同,后者是先意义不同,后者是先p=p+1p=p+1,再获得,再获得p p指向的变量值。指向的变量值。 若若p=ap=a,则输出,则输出* *(p+)(p+)是先输出是先输出a a0 0,再让,再让p p指向指向a a;输出;输出* *(+p)(+p)是先使是先使p p指向指向a a,再输出,再输出p p所指所指的的a a。(5 5)()(* *p p)+表示的是将表示的是将p p指向的变量值指向的变量值+ + 第8章 指针2022-1-27C语言程序设计实用教程第8章408.2.3用数组名作函数参数用数组名作函数参数 用数组名作函数参数时,由于数组名代表的是数组起始地址,因此传递的值是数组首
32、地址,所以要求形参为指针变量。 引入指向数组的指针变量后,数组及指向数组的指针变量作函数参数时,可有种等价形式(本质上是一种,即指针数据作函数参数): (1)形参、实参都用数组名 (2)形参、实参都用指针变量 (3)形参用指针变量、实参用数组名 (4)形参用数组名、实参用指针变量第8章 指针2022-1-27C语言程序设计实用教程第8章41例例8.4 将数组a中n个整数按相反顺序存放。 算法为:将a0与an-1对换,再a1与an-2 对换,直到将a(n-1/2)与an-int(n-1)/2)对换。今用循环处理此问题,设两个“位置指示变量”i和j,i的初值为0,j的初值为n-1。将ai与aj交换
33、,然后使i的值加1,j的值减1,再将ai与aj交换,直到i=(n-1)/2为止,如图所示。第8章 指针2022-1-27C语言程序设计实用教程第8章42第8章 指针2022-1-27C语言程序设计实用教程第8章43程序如下:void inv(int x ,int n) /*形参形参x是数组名是数组名*/ int temp,i,j, m=(n-1)/2; for(i=0;i=m;i+) j=n-1-i; temp=xi;xi=xj;xj=temp; return;第8章 指针2022-1-27C语言程序设计实用教程第8章44main()main() int i,a10=3,7,9,11,0,6,
34、7,5,4,2; int i,a10=3,7,9,11,0,6,7,5,4,2; printf(The original array:n); printf(The original array:n); for(i=0;i10;i+) for(i=0;i10;i+) printf(%d,ai); printf(%d,ai); printf(n); printf(n); inv(a,10); / inv(a,10); /* *实参是数组名实参是数组名* */ / printf(The array has been inverted:n); printf(The array has been inv
35、erted:n); for(i=0;i10;i+) for(i=0;i10;i+) printf(%d,ai); printf(%d,ai); printf(n); printf(n); 第8章 指针2022-1-27C语言程序设计实用教程第8章45对例8.4作一些改动,将函数inv中的形参x改成指针变量。实参为数组名a,即数组a的首地址,将它传给形参指针变量x,这时x就指向a0。x+m是am元素的地址。设i和j以及p都是指针变量,i指向x,j指向x+n-1,使*i与*j交换就是使ai与aj交换。见下例。第8章 指针2022-1-27C语言程序设计实用教程第8章46程序如下:void inv(
36、int *x,int n) /*形参x为指针变量*/ int *p,temp,*i,*j,m=(n-1)/2; i=x;j=x+n-1;p=x+m; for(;i=p;i+,j-)temp=*i;*i=*j;*j=temp;第8章 指针2022-1-27C语言程序设计实用教程第8章47main()int i,a10=3,7,9,11,0,6,7,5,4,2; printf(The original array:n); for(i=0;i10;i+) printf(%d,ai); printf(n); inv(a,10); /*实参是数组名实参是数组名*/ printf(The array ha
37、s benn inverted:n); for(i=0;i10;i+) printf(%d,ai); printf(n);运行情况与前一程序相同。运行情况与前一程序相同。第8章 指针2022-1-27C语言程序设计实用教程第8章48归纳起来,如果有一个实参数组,想在函数中改变此数组的归纳起来,如果有一个实参数组,想在函数中改变此数组的元素的值,实参与形参的对应关系有以下种:元素的值,实参与形参的对应关系有以下种:形参和实参都是数组名。如:形参和实参都是数组名。如:main()int a10; f(a,10) f(int x,int n)这时形参这时形参x和实参和实参a共用一共用一段内存单元。段
38、内存单元。第8章 指针2022-1-27C语言程序设计实用教程第8章49实参用数组,形参用实参用数组,形参用指针变量。如:指针变量。如:main()int a10; f(a,10) f(int *x,int n)第8章 指针2022-1-27C语言程序设计实用教程第8章50实参、形参都用指针变量。如:实参、形参都用指针变量。如:main()int a10,*p=a; f(p,10) f(int *x,int n) 第8章 指针2022-1-27C语言程序设计实用教程第8章51实参为指针变量,形参为数组名。如:实参为指针变量,形参为数组名。如:main()int a10,*p=a; f(p,10
39、) 以上四种方法,本质上都是地址的传递。其中(以上四种方法,本质上都是地址的传递。其中(1)()(4)两)两种只是形式上的不同,实际上都是使用指针变量。种只是形式上的不同,实际上都是使用指针变量。f(int x ,int n) 第8章 指针2022-1-27C语言程序设计实用教程第8章52例例8.6 8.6 用选择法对用选择法对1010个整数排序。个整数排序。main()int *p,i,a10=3,7,9,11,0,6,7,5,4,2;printf(The original array:n);for(i=0;i10;i+) printf(%d,ai); printf(n); p=a; sor
40、t(p,10); for(p=a;pa+10;p+) printf(%d ,*p); printf(n);第8章 指针2022-1-27C语言程序设计实用教程第8章53sort(int x ,int n) int i,j,k,t; for(i=0;in-1;i+) k=i; for(j=i+1;jxk) k=j; if(k!=i) t=xi;xi=xk;xk=t; 说明:函数说明:函数sort用数组名作用数组名作为形参,也可改为用指针变为形参,也可改为用指针变量,这时函数的首部可以改量,这时函数的首部可以改为:为:sort(int *x,int n) 其他可一其他可一律不改。这时将律不改。这时
41、将x定义为指定义为指针变量,在函数中仍可用针变量,在函数中仍可用xi、xk这样的形式表示这样的形式表示数组元素,它就是数组元素,它就是x+i和和x+k所指的数组元素。所指的数组元素。第8章 指针2022-1-27C语言程序设计实用教程第8章54 8.2.4指向多维数组的指针变量指向多维数组的指针变量1.二维数组的地址二维数组的地址设有一个二维数 组a,它有三行四列: int a34=0,1,2,3,4,5,6,7,8,9,10,11 数组名a: 代表整个二维数组的首地址,也就是第0行的首地址。a+i: 代表第i行的首地址。(见下页图) 第8章 指针2022-1-27C语言程序设计实用教程第8章
42、55数组名a代表整个二维数组的首地址:上图 a数组包含三个元素:a0,a1,a2. 而每个元素又是一个一维数组,它包含4个元素(即4个列元素),如:a0又包含:a00,a01,a02,a03.第8章 指针2022-1-27C语言程序设计实用教程第8章56第8章 指针2022-1-27C语言程序设计实用教程第8章57数组及数组元素的地址表示如下:数组及数组元素的地址表示如下: 从二维数组的角度来看,a是二维数组名,a代表整个二维数组的首地址,也是二维数组第0行的首地址,等于1000。a+1代表第一行的首地址,等于1008。如图8.11所示:第8章 指针2022-1-27C语言程序设计实用教程第8
43、章58 一维数组名ai: 代表第i 行的首地址,即第i行中第0列元素的地址(既&ai0)。 ai+j: 代表第i行中的第j个元素的地址,即为&aij。 注意地址变化的单位数值在不同的场合的实际字节数是不同的:“a+1”中的“1”实际代表数组中一行一行元素所占的总字节数;“ai+1”中的“1” 代表数组中一个元素所占的字节数。 第8章 指针2022-1-27C语言程序设计实用教程第8章59a+2 a数组a0a1a2aa+1(1000)(1008)(1016)a代表第0行的首地址,a+1代表第1行的首地址,a+2代表第2行的首地址.每行存放4个整型数据(即1个元素占2个字节),因此
44、,这里+1的含义是:+4*2=+8个字节.第8章 指针2022-1-27C语言程序设计实用教程第8章60注意:(1)从二维数组角度看,数组名a代表数组的起始地址,是一个以行为单位进行控制的行指针:a+i:行指针值,指向二维数组的第:行指针值,指向二维数组的第i行。行。*(a+i):(列)指针值,指向第i行第列(控制由行转为列,但仍为指针)。*(*(a+i):数组元素ai0的值。用a作指针访问数组元素aij的格式:*(*(a+i)j)(2)若a是一个一维数组,则ai代表数组的第i个元素,它占有实际的存储单元。第8章 指针2022-1-27C语言程序设计实用教程第8章61 100011002310
45、0451006710089101011101213101415101617101819102021102223aa+1a+2a0+1a0+2a0+3行地址,元素地址的表示法第8章 指针2022-1-27C语言程序设计实用教程第8章62例例8.7 8.7 用指针表示法输出二维数组的各元素。用指针表示法输出二维数组的各元素。#includemain()static int a23=0,1,2,3,4,5; int k,j,*p; for (j=0;j2;j+) /* 方式方式1 */ for (k=0;k3;k+) printf(%5d,*(aj+k); /* aj是是j行首地址,行首地址,aj+
46、k是是j行行k列元素的地列元素的地址址*/ putchar(n); 第8章 指针2022-1-27C语言程序设计实用教程第8章63接上页:for (j=0;j2;j+) /* 方式方式2 */ for (k=0;k3;k+) printf(%5d,*(*(a+j)+k); /* *(a+j)是是j行首地址,行首地址,*(a+j)+k是是j行行k列元素的地址列元素的地址*/ putchar(n); p=a; /* p指向数组的第一个元素 */ for (j=0;j2;j+) /* 方式方式3 */ for (k=0;k3;k+) printf(%5d,*(p+); /* 输出输出p所指示的元素所
47、指示的元素 */ putchar(n); 第8章 指针2022-1-27C语言程序设计实用教程第8章64 输出的结果是: 0 3 4 5 0 3 4 5 0 3 4 5第8章 指针2022-1-27C语言程序设计实用教程第8章65对二维数组,注意区分以下表示的不同含义:a、二维数组名、数组首址是常量指针。a+i、&ai指向第i行(第i行首址)是二级指针。ai、*(a+i)、&ai0指向第i行第0列是一级指针,其地址值与a+i、&ai相同,注意不要认为*(a+i)是a+i指向的对象,因为在二维数组中,a+i是指向行,而不指向具体的单元。(但在一维数组中指向具体单元)。ai
48、+j、*(a+i)+j表示元素表示元素aij的地址。的地址。*(*(a+i)+j)、)、*(ai+j)表示元素)表示元素aij。第8章 指针2022-1-27C语言程序设计实用教程第8章662. 行指针变量行指针变量指向由指向由n个元素组成的一维数组个元素组成的一维数组的指针变量的指针变量(1)定义格式)定义格式 类型类型 (* *指针变量)指针变量) 元素个数元素个数 注意注意(* *指针变量)指针变量)外的括号不能缺,否则成了指针数组外的括号不能缺,否则成了指针数组数组的每个元素都是一个指针(本章第数组的每个元素都是一个指针(本章第5节介绍)。节介绍)。(2)赋值)赋值 行指针变量二维数组
49、名行指针变量二维数组名; 如: int a34; int (*p)4; p=a;第8章 指针2022-1-27C语言程序设计实用教程第8章67注意:(1)int (*p)4; 定义一个指针变量p ,p 指向包含4个元素的一维数组。(2)p+i与 *(p+i)的区别: p+i是指向第i行的指针(第i行的首地址); *(p+i)是指向第i行第1个元素的地址; 两者数值相等,但含义不同:两者数值相等,但含义不同:p+i p+i 的增值将以行的增值将以行长为单位,而长为单位,而* *(p+i)(p+i)增值将以元素长度为单位。增值将以元素长度为单位。 第8章 指针2022-1-27C语言程序设计实用教
50、程第8章68即:p+i+1将指向第i行再下一行的首地址,而*(p+i)+1将指向第i行首元素的下一个元素地址。(见下图)设 int a34,(*p)4; p=a; p,ap+1p+2a0 a1a2如果p先指向a0,则p+1不是指向a01,而是指向a1第8章 指针2022-1-27C语言程序设计实用教程第8章69例例8.7 main( )static int a34=1,3,5,7,9,11,13,15,17,19,21,23;int (*p)4,i,j;p=a;scanf(i=%d,j=%d,&i,&j); printf(a%d%d=%dn, i, j, *(*(p+i)+j)
51、 );第8章 指针2022-1-27C语言程序设计实用教程第8章70例例8.8 用指向二维数组的指针变量输出二维数组,并将数组中的最大元素及所在行列号输出。main() int a34=1,3,5,7,9,11,13,15,17,19,21,23;int i,j,max,*p;int row=0,col=0; p=a0; /*指针p指向数组a的第0行第0列*/max=*p; /*先把第一个元素作为最大值*/for (i=0;i3;i+) printf(“n”);for(j=0;j4;j+)printf(“%5d”,*p);if (max*p) max=*p; row=i;col=j;p+;pr
52、intf(“n max is:a%2d%2d=%-4d”, row,col,max);第8章 指针2022-1-27C语言程序设计实用教程第8章71运行结果:运行结果:1 3579 11 131517192123max is:a23=23第8章 指针2022-1-27C语言程序设计实用教程第8章72例例8.9 用行指针变量输出二维数组,并将用行指针变量输出二维数组,并将数组中的最大元素及所在行列号输出。数组中的最大元素及所在行列号输出。 main() int a34=1,3,5,7,9,11,13,15,17,19,21,23; int i, j, max, row=0,col=0; int
53、(*p)4; /*定义p为指向一个有4个元素的行指针变量*/ p=a; /*指针p指向数组a的第0行*/ max=*p; /*先把第一个元素作为最大值*/ for (i=0;i3;i+) printf(“n”);第8章 指针2022-1-27C语言程序设计实用教程第8章73for(j=0;j4;j+)printf(“%5d”,*(*p+j); /* *(*p+j)相当于相当于*(*(p+0)+j)是第是第0行第行第j列的元素列的元素 */if (max=n) p+=n-1; /*指针指到要复制的第一个字符指针指到要复制的第一个字符 */ 第8章 指针2022-1-27C语言程序设计实用教程第8
54、章79for (;*p!=0;p+,q+) *q=*p; *q=0; /* 字符串以0 结尾 */ printf(String a : %sn,a); printf(String b : %sn,b); 输入输入: 3 输出输出: computer mputer考虑一下,若输出语句改为如下语句会如何?考虑一下,若输出语句改为如下语句会如何?printf(“string a is :%sn”,p);printf(“string b is %sn”,q);第8章 指针2022-1-27C语言程序设计实用教程第8章808.3.2 8.3.2 字符串指针作函数参数字符串指针作函数参数 将一个字符串从一
55、个函数传递到另一将一个字符串从一个函数传递到另一个函数,可以用地址传递的方法,即用字个函数,可以用地址传递的方法,即用字符数组名作参数或用指向字符串的指针变符数组名作参数或用指向字符串的指针变量作参数。在被调用的函数中可以改变字量作参数。在被调用的函数中可以改变字符串的内容,在主调函数中可以得到改变符串的内容,在主调函数中可以得到改变了的字符串。了的字符串。第8章 指针2022-1-27C语言程序设计实用教程第8章81例例8.158.15 用函数调用实现字符串的复制。用函数调用实现字符串的复制。 void copy_string(char from,char to) int i =0; whi
56、le(fromi!=0) toi=fromi;i+; toi=0; 第8章 指针2022-1-27C语言程序设计实用教程第8章82main() char a=”I am a teacher.”;char b=”you are a student.”;printf(“string a=%snstring b=%sn”,a,b);copy_string(a,b);printf(“nstring a=%snstring b=%sn”,a,b);运行结果如下:string a=I am a teacher.string b=you are a student.string a=I am a teach
57、er.string b=I am a teacher.第8章 指针2022-1-27C语言程序设计实用教程第8章838.3.3 字符串数组字符串数组字符串数组:是指数组中的每个元素都是一个存放字符串的数组。字符串数组可以用一个二维字符数组来存储字符串数组可以用一个二维字符数组来存储。例如:char languge3 10;数组的第一个下标决定字符串的个数,第二个下标是字符串的最大长度(实际最多9个字符,0占一位置)。可以对字符串数组赋初值。例如:char languge3 10;=“Basic”, “c+”, “pascal”第8章 指针2022-1-27C语言程序设计实用教程第8章84lan
58、guage0language1language2其内存存储情况如图8.14所示:B A SIC 0C +0P A SC A L 0由于字符数组变量在定义时就确定了大小,每行元素都是固由于字符数组变量在定义时就确定了大小,每行元素都是固定的,而字符串长度不等,这样会浪费存储空间。使用字符定的,而字符串长度不等,这样会浪费存储空间。使用字符型指针数组可以更方便地处理字符串数组。型指针数组可以更方便地处理字符串数组。第8章 指针2022-1-27C语言程序设计实用教程第8章858.4 8.4 指针数组与命令行参数指针数组与命令行参数8.4.1 8.4.1 指针数组指针数组 指针数组:是指针变量的集合
59、。即它的每一个元素都是指针变量,且都具有相同的存储类别和指向相同的数据类型。指针数组的定义形式为: 类型标识符 *数组名数组长度说明;例如: int *p10;由于 比*的优先级高,因此p先与 10结合成p10,而p10正是数组的定义形式,共有10个元素。最后p10与*结合,表示它的各元素可以指向一个整型变量。第8章 指针2022-1-27C语言程序设计实用教程第8章86指针数组广泛应用于对字符串的处理指针数组广泛应用于对字符串的处理例如有定义:例如有定义: char *p3;定义了一个具有三个元素定义了一个具有三个元素p0,p1,p2的指针数组。的指针数组。每个元素都可以指向一个字符数组,或
60、字符串。每个元素都可以指向一个字符数组,或字符串。若利用数组初始化,则:若利用数组初始化,则:char *p3= “Basic”, “c+”, “pascal”; p0指向字符串指向字符串“Basic”;p1指向字符串指向字符串“c+”;p2指向字符串指向字符串“pascal” ;第8章 指针2022-1-27C语言程序设计实用教程第8章87B A S I C 0C + + 0P A S C A L 0p0p1p2其存储结构如图其存储结构如图8.158.15所示。所示。p0p0指向字符串指向字符串“BASIC”BASIC”;p1p1指向字符串指向字符串“C+”C+”;p2p2指向字符串指向字符串“PASCAL” PASCAL” ; 第8章 指针2022-1-27C语言程序设计实用教程第8章88例8.9 字符指针数组的赋值 #define NULL 0 main( ) static char a =“Fortran”; static char b =“COBOL”; static char c =“Pascal”; int i; char *p4; p0=a; p1=b; p2=c; p3=NULL; for (i=0
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 项目管理执行能力试题及答案
- 2025年国内外投资环境的比较研究试题及答案
- 注会考生考前心理疏导技巧试题及答案
- 2024年项目管理资格考试考前准备的全景分析试题及答案
- 注册会计师考试内容更新与变化分析试题及答案
- 橡皮坝河道清淤施工方案
- 贴心指导证券从业资格试题及答案
- 注册会计师理论与实践试题及答案
- 生物技术在生态修复工程中的应用考核试卷
- 2024年项目管理协作机制试题及答案
- 12J12无障碍设施图集
- 【八年级下册地理中图北京版】期中真题必刷卷B-【期中真题必刷卷】(北京专用)(解析版)
- 《铁路技术管理规程》(普速铁路部分)
- 白细胞疾病及其检验(血液学检验课件)
- 案例3 哪吒-全球首个“海空一体”跨域航行器平台
- 车队运营中的司机管理策略研究
- 新生儿脐部出血的护理
- 实验室的智能化设计与建设
- 《中国海洋大学》课件
- 《盐津铺子公司盈利能力探析实例报告(10000字论文)》
- 2025年中考语文课内名著阅读专题复习:第10部 《水浒传》课件
评论
0/150
提交评论