指针PPT讲座1.内存单元地址程序中定义了变量后,在编译时系统就给这个变量分配内存单元。内存中每一个内存单元都有一个编号,这就是“地址”。内存单元地址就是编译后系统分配给变量的内存空间位置。例如:inti,j,k;8.1地址和指针的概念内存用户数据区┇变量k变量j变量i┇200020022004其中2000为i的地址2002为j的地址2004为k的地址⑶数据在内存中的存取方式:直接访问方式和间接访问方式。直接访问方式:按变量地址存取变量值。间接访问方式:把一个变量的地址放在另一个变量中。⑵内存单元的内容——内存单元中存放的数值。例如:i=3;j=6;在2000单元中存放数值3,3即为内容。在2002单元中存放数值6,6即为内容。变量i变量j┇63┇20002002例:printf(%d,i);其执行是这样的:根据变量名与地址的对应关系,找到变量i的地址2000,然后从由2000开始的两个字节中取出数据(即变量的值3),把它输出。这种按变量地址存取变量值的方式称为“直接访问”方式。例如,我们定义一个变量i_pointer,用来存放整型变量i的地址:i_pointer=&i;/*把变量i的地址赋给变量i_pointer*/这时i_pointer的值就是变量i所占用的内存单元的起始地址(2000)。如何存取变量i的值?变量i变量j┇┇200063┇20002002变量i_pointer3010间接访问方式:通过存储在某一个内存单元中的地址去存取该地址所指向的内存单元中的变量值。要存取变量i的值,先要找到存放i的地址的变量(i_pointer),从中取出i的地址(2000),然后到2000、2001字节中取出i的值(3)。表示将数值3送到变量中,有两种方法:①将3送到变量i所标志的单元中。②将3送到变量i_pointer所“指向”的单元中。所谓“指向”就是通过地址来体现的。(如右图所示)由于通过地址可以找到所需的变量单元,因此可以说,地址“指向”该内存单元。在C语言中,将地址形象化地称为“指针”。一个变量的地址称为该变量的“指针”。例如地址2000是变量i的指针。如果有一个变量,专门用来存放另一个变量的地址(即指针),则它称为“指针变量”。如前面所说的i_pointer变量称为指针变量。指针变量的值是指针(地址)。注意:(1)“指针”和“指针变量”这两个不同的概念。(2)通过指针变量如何访问变量i的值?(间接访问)2000i32000i32000i_pointer变量的指针就是变量的地址。存放变量地址的变量是指针变量,用来指向另一个变量。指针变量和它所指向的变量之间,用“*”表示“指向”。例如i_pointer代表指针变量,*i_pointer是i_pointer所指向的变量。8.2变量的指针和指向变量的指针变量*i_pointer200032000i_pointeri可以看到,*i_pointer也代表一个变量,它和变量i是同一回事。下面两个语句作用相同:①i=3;②*i_pointer=3;第②个语句的含义是将3赋给指针变量i_pointer所指向的变量。8.2.1定义一个指针变量指针变量是专门用来存放地址的,因此必须定义为“指针类型”。指针变量定义的一般形式:基类型*指针变量名指针变量的基类型用来指定该指针变量可以指向的变量的类型。例如:int*pointer_1,*pointer_2;(指向整型变量的指针变量)float*pointer_3;(指向实型变量的指针变量)char*pointer_4;(指向字符型变量的指针变量)注意:1.指针变量前面的“*”表示该变量是指针变量。指针变量名是pointer_1、pointer_2,而不是*pointer_1、*pointer_2.2.在定义指针变量时必须指定基类型。不同类型的数据在内存中所占的字节数是不同的。指针变量的类型说明是为了告诉系统按变量中的地址从内存选取几个字节的数据进行操作,便于指针的移动和指针的运算操作。3.一个指针变量只能指向同一类型的变量,即存放同一类型变量的地址。怎样使一个指针变量指向另一个变量呢?可以使用赋值语句。例如:floatx;charch;float*pointer_3;char*pointer_4;pointer_3=&x;pointer_4=&ch;例:intk,i=5;int*pointer;pointer=&i;k=*pointer;printf(%d,k);printf(%d,*pointer);2000(地址)pointer20005(数据)*pointeri2000输出变量i的值5k的值为58.2.2指针变量的引用指针变量中只能存放地址(指针),不能将一个整型量或任何其它非地址类型的数据赋给一个指针变量。例如赋值语句:pointer_1=2000;(不合法)有关地址的运算符:1.&——取地址运算符。2.*——指针运算符(或称“间接访问”运算符)。例如:&a---表示变量a的地址*p---表示指针变量p所指向的变量(地址p所指的单元中存放的值)main(){inta,b;int*pointer_1,*pointer_2;/*定义指针变量,指向整型变量*/a=100;b=10;pointer_1=&a;/*使pionter_1指向a*/pointer_2=&b;/*使pionter_2指向b*/printf(%d,%d\n,a,b);printf(%d,%d\n,*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。&和*的优先级相同,按自右向左方向结合。因此,先执行*pointer_1的运算,它的执行结果就是变量a,再执行&运算,则&*pointer_1的最后结果与&a相同,即取变量a的地址。(见图示1)&a&bpointer_2bapointer_1图示1*pointer_1*pointer_2a&a&apointer_2bpointer_1图示2*pointer_2*pointer_1下面对“&”和“*”运算符再做些说明:⑴如有pointer_1=&a;pointer_2=&b;则表达式&*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_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(){inta,b,*p1,*p2,*p;scanf(%d,%d,&a,&b);p1=&a;p2=&b;if(ab){p=p1;p1=p2;p2=p;}printf(a=%d,b=%d\n,a,b);printf(max=%d,min=%d\n,*p1,*p2);}例8.2输入整数a和b,按先大后小的顺序输出a和b。&a&bp1p259abp&b&ap1p259abp&a运行结果:a=5,b=9max=9,min=5实际上并没有交换a和b。算法不交换整型变量的值(变量a和b中的值没有改变),而是交换两个指针变量的值(即变量a和b的地址),使p1指向大的数,p2指向小的数。8.2.3指针变量作为函数参数例:对输入的两个整数按大小顺序输出。#includestdio.hvoidmain(){voidswap(int*p1,int*p2);inta,b;int*pointer_1,*pointer_2;scanf(″%d,%d″,&a,&b);pointer_1=&a;pointer_2=&b;if(a<b)swap(pointer_1,pointer_2);printf(″\n%d,%d\n″,a,b);}voidswap(int*p1,int*p2){inttemp;temp=*p1;*p1=*p2;*p2=temp;}例:对输入的三个整数按大小顺序输出。#includestdio.hvoidmain(){inta,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);}voidexchange(int*q1,int*q2,int*q3){if(*q1*q2)swap(q1,q2);if(*q1*q3)swap(q1,q3);if(*q2*q3)swap(q2,q3);}voidswap(int*pt1,int*pt2){inttemp;temp=*pt1;*pt1=*pt2;*pt2=temp;}一个变量有地址,一个数组包含若干元素,每个元素在内存中占用存储单元,它们也应该有相应的地址。一个变量既然可以指向变量,当然也可以指向数组和数组元素。所谓数组的指针是指数组的起始地址。数组元素的指针是数组元素的地址。例如:inta[10],i,*p,*p1;p=a;或p=&a[0];p1=&a[6];a[0]a[1]a[6]......&a[0]&a[1]&a[6]app1=&a[6]p18.3数组的指针和指向数组的指针变量引用数组元素可以用下标法(如a[3]),也可以用指针法,即通过指向数组元素的指针找到所需的元素。使用指针法能使目标程序质量高(占用内存少,运行速度快)。8.3.1指向数组元素的指针例如:inta[10];int*p;...p=&a[0];•指向数组元素的指针变量,其定义与普通指针变量的定义相同。把元素a[0]的地址赋给p,即p指向数组a的第0个元素。因为数组名表示数组的首地址,所以它等价于p=a;应注意数组a并不代表整个数组,而是把数组a的首地址赋给指针变量p,不是把数组a的各个元素赋给p。•指针变量定义的同时可以赋初值:inta[10];int*p=&a[0];定义时也可以写成如下形式:int*p=a;相当于int*p;p=&a[0];a数组a[0]a[1]a[2]a[i]p*(p+i)a[10]&a[0]假设已经定义了数组和一个指针变量inta[10];int*p=a;...*p=1;数组元素的引用可以用1.下标法:a[i]2.指针法:*(a+i)或*(p+i)其中p为指向数组a的指针变量,初值p=a;下标法比较直观,程序容易阅读指针表示8.3.2通过指针引用数组元素对p当前所指的元素赋整数值1注意:1.C规定:p+1(或p++)指向同一数组的下一个元素(不是地址值简单加1)。p+1代表的实际地址是p+1×d(d是一个数组元素所占的字节数)。2.当p的初值为a的首地址时,p+i或a+i就是a[i]的地址,因为a代表了数组的首地址。3.*(p+i)或*(a+i)所指的数组元素就是a[i]的内容。实际上,[]是变址运算符,对a[i]的处理,是将a[i]按a+i计算地址,然后找出此地址单元中的值。4.指向数组的指针变量也可以带下标,如:p[i]等价于*(p+i),即a[i]。a数组a[0]a[1]a[2]a[i]p+1或a+1pp+2或a+2p+i或a+i*(p+i)p+9或a+9a[9]例8