第八章-指针(课堂PPT).ppt
《第八章-指针(课堂PPT).ppt》由会员分享,可在线阅读,更多相关《第八章-指针(课堂PPT).ppt(74页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、第第8章章 指指 针针 指针指针是是C 语言中的一个重语言中的一个重要概念,是要概念,是C 语言的语言的 精华、灵精华、灵魂魂。1.内存单元地址内存单元地址程序中定义了变量后,在程序中定义了变量后,在编译时编译时系统就给这个变量分配内存单元。系统就给这个变量分配内存单元。内存中每一个内存单元都有一个编号,这就是内存中每一个内存单元都有一个编号,这就是“地址地址”。内存单元地址内存单元地址 就是编译后系统分配给变量的就是编译后系统分配给变量的内存空间位置内存空间位置。例如:例如:int i,j,k;8.1 地址和指针的概念地址和指针的概念内存用户数据区内存用户数据区变量k变量j变量i200020
2、022004其中其中2000为为 i 的地址的地址 2002为为 j 的地址的地址 2004为为 k 的地址的地址 数据在内存中的存取方式:数据在内存中的存取方式:直接访问方式直接访问方式 和和 间接访问方式。间接访问方式。直接访问方式:直接访问方式:按变量地址存取变量值。按变量地址存取变量值。间接访问方式:间接访问方式:把一个变量的地址放在另一个变量中把一个变量的地址放在另一个变量中。内存单元的内容内存单元的内容 内存单元内存单元中存放的中存放的数值数值。例如:例如:i=3;j=6;在在2000单元中存放数值单元中存放数值 3,3 即为即为内容内容。在在2002单元中存放数值单元中存放数值
3、6,6 即为即为内容内容。变量 i变量 j 6320002002例:例:printf(%d,i);其执行是这样的:其执行是这样的:根据变量名与地址的对应关系根据变量名与地址的对应关系,找到变,找到变量量i 的地址的地址2000,然后从由,然后从由2000开始的两个字节中取出数据(即变开始的两个字节中取出数据(即变量的值量的值3),把它输出。),把它输出。这种按变量地址存取变量值的方式称为这种按变量地址存取变量值的方式称为“直接访问直接访问”方式。方式。例如,我们定义一个变量例如,我们定义一个变量 i_pointer,用来存放整型变量,用来存放整型变量i 的地址:的地址:i_pointer=&i
4、;/*把变量把变量 i 的地址的地址赋给变量赋给变量 i_pointer*/这时这时i_pointer的值的值 就是变量就是变量 i 所占用的内存单元的所占用的内存单元的起始地址起始地址(2000)。)。如何存取变量如何存取变量i 的值?的值?变量 i变量 j 20006320002002变量变量i_pointer3010间接访问方式间接访问方式:通过存储在某一个内存单元中的地址去存取该地址所通过存储在某一个内存单元中的地址去存取该地址所指向的内存单元中的变量值。指向的内存单元中的变量值。要存取变量要存取变量i 的值,的值,先要找到存放先要找到存放i 的地址的的地址的变量(变量(i_point
5、er),从中),从中取出取出i 的地址(的地址(2000),),然后到然后到2000、2001字节字节中取出中取出i 的值(的值(3)。)。表示将数值表示将数值3送到变量中,有两种方法:送到变量中,有两种方法:将将3 送到变量送到变量i 所标志的单元中。所标志的单元中。将将3 送到变量送到变量i_pointer 所所“指向指向”的单元中。的单元中。所谓所谓“指向指向”就是通过地址来体现的。就是通过地址来体现的。(如右图所示)(如右图所示)由于通过地址可以找到所需的变量单元,因此可以说,由于通过地址可以找到所需的变量单元,因此可以说,地址地址“指向指向”该该内存单元内存单元。在。在C 语言中,语
6、言中,将地址形象化地称为将地址形象化地称为“指针指针”。一个变量的地址称为该变量的一个变量的地址称为该变量的“指针指针”。例如地址。例如地址2000是变量是变量i的指针。的指针。如果有一个变量,专门用来存放另一个变量的地址(即指针),则它称如果有一个变量,专门用来存放另一个变量的地址(即指针),则它称为为“指针变量指针变量”。如前面所说的。如前面所说的i_pointer变量称为变量称为指针变量。指针变量。指针变量的值指针变量的值是指针(地址)。是指针(地址)。注意:注意:(1)“指针指针”和和“指针变量指针变量”这两个不同的概念。这两个不同的概念。(2)通过指针变量如何访问变量通过指针变量如何
7、访问变量 i 的值?的值?(间接访问间接访问)2000i32000i32000i_pointer 变量的指针变量的指针就是变量的地址。存放变量地址的变量是就是变量的地址。存放变量地址的变量是指针变量,指针变量,用来指用来指向另一个变量。向另一个变量。指针变量和它所指向的变量之间,用指针变量和它所指向的变量之间,用“*”表示表示“指向指向”。例如例如 i_pointer代表指针变量,代表指针变量,*i_pointer 是是i_pointer所指向的变量。所指向的变量。8.2 变量的指针和指向变量的指针变量变量的指针和指向变量的指针变量*i_pointer200032000i_pointeri可以
8、看到,可以看到,*i_pointer也代表一个变也代表一个变量,它和变量量,它和变量i 是同一回事。下面两是同一回事。下面两个语句作用相同:个语句作用相同:i=3;*i_pointer=3;第第个语句的含义是将个语句的含义是将3 赋给指针变赋给指针变量量i_pointer所指向的变量。所指向的变量。8.2.1 定义一个指针变量定义一个指针变量指针变量是专门用来存放地址的,因此必须定义为指针变量是专门用来存放地址的,因此必须定义为“指针类型指针类型”。指针变量定义的一般形式指针变量定义的一般形式:基类型基类型 *指针变量名指针变量名指针变量的基类型指针变量的基类型 用来指定该指针变量可以指向的变
9、量的类型。用来指定该指针变量可以指向的变量的类型。例如例如:int *pointer_1,*pointer_2;(指向整型变量的指针变量)float *pointer_3;(指向实型变量的指针变量)char *pointer_4;(指向字符型变量的指针变量)注意注意:1.指针变量前面的指针变量前面的“*”表示该变量是指针变量。表示该变量是指针变量。指针变量名指针变量名是是 pointer_1、pointer_2,而不是,而不是*pointer_1、*pointer_2.2.在定义指针变量时必须指定基类型。在定义指针变量时必须指定基类型。不同类型的数据在内存中所占的字节数是不同的。不同类型的数据
10、在内存中所占的字节数是不同的。指针变量的类型说明指针变量的类型说明 是为了告诉系统按变量中的地址从内存选取是为了告诉系统按变量中的地址从内存选取几个字节几个字节的数据进行操作,便于的数据进行操作,便于 指针的移动和指针的运算操作。指针的移动和指针的运算操作。3.一个指针变量只能一个指针变量只能 指向同一类型的变量,即存放同一类型变量的地址。指向同一类型的变量,即存放同一类型变量的地址。怎样使一个指针变量指向另一个变量呢?怎样使一个指针变量指向另一个变量呢?可以使用赋值语句。可以使用赋值语句。例如:例如:float x;char ch;float *pointer_3;char *pointer
11、_4;pointer_3=&x;pointer_4=&ch;例:例:int k,i=5;int *pointer;pointer=&i;k=*pointer;printf(%d,k);printf(%d,*pointer);2000(地址地址)pointer20005(数据数据)*pointeri2000输出变量输出变量 i 的值的值5k的值为58.2.2 指针变量的引用指针变量的引用指针变量中只能存放地址(指针)指针变量中只能存放地址(指针),不能将一个整型量或任何其它,不能将一个整型量或任何其它非地址类型的数据赋给一个指针变量。非地址类型的数据赋给一个指针变量。例如赋值语句:例如赋值语句:
12、pointer_1=2000;(不合法)(不合法)有关地址的运算符有关地址的运算符:1.&取地址运算符。取地址运算符。2.*指针运算符(或称指针运算符(或称“间接访问间接访问”运算符)。运算符)。例如例如:&a-表示变量表示变量a的地址的地址 *p-表示指针变量表示指针变量p 所指向的变量所指向的变量(地址地址p所指的单元中存放的值所指的单元中存放的值)main()int a,b;int*pointer_1,*pointer_2;/*定义指针变量定义指针变量,指向整型变量指向整型变量*/a=100;b=10;pointer_1=&a;/*使使pionter_1指向指向a*/pointer_2=
13、&b;/*使使pionter_2指向指向b*/printf(%d,%dn,a,b);printf(%d,%dn,*pointer_1,*pointer_2);例例8.1 通过指针变量访问整型变量。通过指针变量访问整型变量。运行结果:运行结果:100,10100,10&a(地址地址)pointer_1100(数据数据)*pointer_1a&b(地址地址)pointer_210(数据数据)*pointer_2bpointer_1 指向指向a,*pointer_1 就是变量就是变量a。pointer_2 指向指向b,*pointer_2就是变量就是变量b。&和和*的优先级相同,按的优先级相同,按自
14、自右向左右向左方向结合。因此,先方向结合。因此,先执行执行*pointer_1 的运算,的运算,它的执行结果就是变量它的执行结果就是变量 a,再执行再执行&运算,则运算,则&*pointer_1的最后结果与的最后结果与&a 相同,相同,即取变量即取变量 a 的地的地址。址。(见图示1)&a&bpointer_2b apointer_1图示1*pointer_1*pointer_2a&a&apointer_2bpointer_1图示2*pointer_2*pointer_1下面对下面对“&”和和“*”运算符再做些说明:运算符再做些说明:如有如有 pointer_1=&a;pointer_2=&b
15、;则则 表达式表达式&*pointer_1 的含义是什么?的含义是什么?pointer_2=&a;如果有如果有 pointer_2=&*pointer_1;则结果如何?则结果如何?先执行先执行&a 运算,得运算,得 a 的地址,再执行的地址,再执行*运算,运算,得变量得变量 a 的值。的值。所以所以,表达式表达式*&a 和表达式和表达式 *pointer_1 的含义是相同的,它们等价于变量的含义是相同的,它们等价于变量a。即即*&a 与与a 等价。等价。(3)(*pointer_1)+相当于相当于 a+,变量变量a 的值加的值加1。(4)*pointer_1+相当于相当于 *(pointer_
16、1+)。这是由于这是由于*和和+优先级别相同,结合方向是优先级别相同,结合方向是自右而左自右而左。+在在pointer_1的右侧,是的右侧,是“后加后加”,因此,因此先执行先执行*pointer_1,取取出出 a 的值的值,然后,然后指针指针 pointer_1加加1,这时,这时pointer_1就不再指向就不再指向a 了。了。注意:注意:(3)和和(4)的运算结果是不同的。的运算结果是不同的。apointer_1&a5*pointer_1*&a(2)如有如有 pointer_1=&a;则表达式则表达式*&a 的含义是什么?的含义是什么?main()int a,b,*p1,*p2,*p;sca
17、nf(%d,%d,&a,&b);p1=&a;p2=&b;if(ab)p=p1;p1=p2;p2=p;printf(a=%d,b=%dn,a,b);printf(max=%d,min=%dn,*p1,*p2);例例8.2 输入整数输入整数a和和b,按先大后小的顺序输出,按先大后小的顺序输出a和和b 。&a&b p1p2 5 9 ab p&b&a p1p2 5 9 ab p&a运行结果运行结果:a=5,b=9 max=9,min=5实际上并没有交换实际上并没有交换a 和和b。算法不交换整型变量。算法不交换整型变量的值(变量的值(变量a和和 b中的值没有改变),而是交换中的值没有改变),而是交换两个
18、指针变量的值(即变量两个指针变量的值(即变量a和和 b的地址),使的地址),使p1指向大的数,指向大的数,p2指向小的数。指向小的数。8.2.3 指针变量作为函数参数指针变量作为函数参数例:对输入的两个整数按大小顺序输出。例:对输入的两个整数按大小顺序输出。#include void main()void swap(int*,int*);int,;int*pointer_,*pointer_;scanf(,);pointer_;pointer_2;if()swap(pointer_,pointer_2);printf(,);void swap(int*,int*)int temp;temp*1
19、;*;*temp;例:对输入的三个整数按大小顺序输出。例:对输入的三个整数按大小顺序输出。#includevoid main()int a,b,c,*p1,*p2,*p3;scanf(%d,%d,%d,&a,&b,&c);p1=&a;p2=&b;p3=&c;exchange(p1,p2,p3);printf(n%d,%d,%d n,a,b,c);void exchange(int*q1,int*q2,int*q3)if(*q1*q2)swap(q1,q2);if(*q1*q3)swap(q1,q3);if(*q2*q3)swap(q2,q3);void swap(int*pt1,int*pt2
20、)int temp;temp=*pt1;*pt1=*pt2;*pt2=temp;一个变量有地址,一个数组包含若干元素,每个元素在内存中占用一个变量有地址,一个数组包含若干元素,每个元素在内存中占用存储单元,它们也应该有相应的地址。一个变量既然可以指向变量,当然存储单元,它们也应该有相应的地址。一个变量既然可以指向变量,当然也可以指向数组和数组元素。也可以指向数组和数组元素。所谓所谓数组的指针数组的指针是指是指 数组的数组的起始地址。起始地址。数组元素的指针数组元素的指针是是数组元素的地址数组元素的地址。例如:例如:int a10,i,*p,*p1;p=a;或或 p=&a0;p1=&a6;a0a
21、1a6.&a0&a1&a6 app1=&a6p18.3 数组的指针和指向数组的指针变量数组的指针和指向数组的指针变量 引用数组元素可以用下标法(如引用数组元素可以用下标法(如a3),也可以用指针法,即通过指向数也可以用指针法,即通过指向数组元素的指针找到所需的元素。使用指组元素的指针找到所需的元素。使用指针法能使目标程序质量高(占用内存少,针法能使目标程序质量高(占用内存少,运行速度快)。运行速度快)。8.3.1 指向数组元素的指针指向数组元素的指针例如例如:int a10;int *p;.p=&a0;指向数组元素的指针变量,其定义与普通指针变量的定义相同。指向数组元素的指针变量,其定义与普通
22、指针变量的定义相同。把元素把元素a0 的地址赋给的地址赋给 p,即即p指向指向 数组数组a 的第的第0个元个元素。素。因为数组名表示数组的首地址,所以它因为数组名表示数组的首地址,所以它 等价于等价于 p=a;应注意数组应注意数组a 并不代表整个数组并不代表整个数组,而是把数组,而是把数组a 的首地址赋的首地址赋给指针变量给指针变量p,不是把数组,不是把数组a 的各个元素赋给的各个元素赋给p。指针变量定义的同时指针变量定义的同时 可以可以赋初值赋初值:int a10;int *p=&a0;定义时也可以写成如下形式:定义时也可以写成如下形式:int*p=a;相当于相当于 int*p;p=&a0;
23、a 数组数组a0a1a2aip*(p+i)a10&a0假设已经定义了数组和一个指针变量假设已经定义了数组和一个指针变量 int a10;int*p=a;.*p=1;数组元素的引用可以用数组元素的引用可以用 1.下标法下标法:ai2.指针法指针法:*(a+i)或或*(p+i)其中其中p 为指向数组为指向数组a 的指针的指针变量,初值变量,初值 p=a;下标法比较直观下标法比较直观,程序容易阅读程序容易阅读指针表示指针表示8.3.2 通过指针引用数组元素通过指针引用数组元素对对p 当前所指的当前所指的元素元素 赋整数值赋整数值1注意注意:1.C规定规定:p+1(或或p+)指向同一数组的下指向同一数
24、组的下一个元素一个元素(不是地址值简单加不是地址值简单加1)。p+1代代表的实际地址是表的实际地址是 p+1d(d是一个数组是一个数组元素所占的字节数)。元素所占的字节数)。2.当当 p 的初值为的初值为 a 的首地址时的首地址时,p+i 或或 a+i 就是就是ai 的地址,因为的地址,因为 a 代表了数组的代表了数组的首地址。首地址。3.*(p+i)或或*(a+i)所指的数组元素就是所指的数组元素就是ai 的内容。的内容。实际上,实际上,是变址运算是变址运算符,对符,对ai 的处理,是将的处理,是将ai 按按a+i 计算计算地址,然后找出此地址单元中的值。地址,然后找出此地址单元中的值。4.
25、指向数组的指针变量也可以带下标指向数组的指针变量也可以带下标,如如:pi 等价于等价于*(p+i),即,即ai。a 数组数组a0a1a2aip+1 或或 a+1pp+2 或或 a+2p+i 或或 a+i*(p+i)p+9 或或 a+9a9例例8.5 输出数组中全部元素输出数组中全部元素:四种方法。种方法。main()int a10=1,2,3,4,5,6,7,8,9,10;int*p,i;printf(n下标法下标法:n);for(i=0;i10;i+)printf(%d,ai);printf(n指针法指针法(数组名数组名):n);for(i=0;i10;i+)printf(%d,*(a+i)
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 第八 指针 课堂 PPT
限制150内