C++大学基础教程第六章市公开课一等奖省赛课获奖课件_第1页
C++大学基础教程第六章市公开课一等奖省赛课获奖课件_第2页
C++大学基础教程第六章市公开课一等奖省赛课获奖课件_第3页
C++大学基础教程第六章市公开课一等奖省赛课获奖课件_第4页
C++大学基础教程第六章市公开课一等奖省赛课获奖课件_第5页
已阅读5页,还剩69页未读 继续免费阅读

下载本文档

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

文档简介

C++大学基础教程第6章指针和引用

北京科技大学计算机系/10/101北京科技大学计算机系C++大学基础教程第六章第1页第六章指针和引用6.1指针概念6.2指针运算6.3指针和函数6.4指针和字符串6.5经过指针访问数组6.6指针访问动态内存6.7引用概念/10/102北京科技大学计算机系C++大学基础教程第六章第2页关于内存地址内存空间访问方式经过变量名访问经过地址访问地址运算符:&例:intvar;则&var表示变量var在内存中起始地址/10/103北京科技大学计算机系C++大学基础教程第六章第3页申明例:staticinti;staticint*i_pointer=&i;

指向整型变量指针指针变量概念概念指针:地址

用于间接访问变量指针变量:

用于存放地址变量目标变量:

3i_pointer*i_pointeri内存用户数据区变量i变量j变量

i_pointer363010引用例1:i=3;例2:*i_pointer=3;指针/10/104北京科技大学计算机系C++大学基础教程第六章第4页小结几个概念:指针,指针变量,目标变量符号*:在定义中表示变量为指针变量运算符:&:取地址运算符*:指向运算符/10/105北京科技大学计算机系C++大学基础教程第六章第5页指针变量定义和初始化语法形式

[存放类型]

数据类型*指针名=初始地址;例:inta;int*pa=&a;注意事项用变量地址作为初值时,该变量必须在指针初始化之前已说明过,且变量类型应与指针类型一致。能够用一个已赋初值指针去初始化另一个指针变量。charch1=’Y’,ch2=’A’;char*pch1=&ch1,*pch2=&ch2;/10/106北京科技大学计算机系C++大学基础教程第六章第6页

例1指针概念main(){inta;int*pa=&a;a=10;cout<<"a:"<<a<<endl;cout<<"*pa"<<*pa<<endl; cout<<"&a:(Hex)"<<HEX<<&a<<endl; cout<<"pa:(HEX)"<<HEX<<pa<<endl; cout<<"&pa:(HEX)"<<HEX<<&pa<<endl;}

a:10*pa:10&a:bb4(HEX)pa:bb4(HEX)&pa:bb2(HEX)/10/107北京科技大学计算机系C++大学基础教程第六章第7页6.2指针运算

/10/108北京科技大学计算机系C++大学基础教程第六章第8页6.2指针运算表6.1指针运算/10/109北京科技大学计算机系C++大学基础教程第六章第9页6.2.1指针赋值运算

指针=地址指针赋值运算一定是地址赋值。用来对指针变量赋值能够是:同类型变量地址;同类型已经初始化指针变量;其它同类型指针。“地址”中存放数据类型与指针类型必须相符。注意:不一样类型指针是不能够相互赋值。在指针赋值时,不存在类型自动转换机制。向指针变量赋值必须是地址常量或变量,不能是普通整数。但能够赋值为整数0,表示空指针。另外,也能够用0或者NULL对指针变量赋值。使得变量包含是“空指针”,即不指向任何内存物理地址。/10/1010北京科技大学计算机系C++大学基础教程第六章第10页

例6.1观察以下指针赋值运算结果。假如将注释去掉,结果将怎样?#include<iostream>usingnamespacestd;voidmain(){intva1=100,*pva1;floatvf1=1.0,*pvf1,*pvf2;int*pva2=NULL;cout<<"valueofpva2is"<<pva2<<endl;pva1=&va1;pvf1=pvf2=&vf1;cout<<pva1<<""<<&va1<<endl;cout<<pvf1<<""<<pvf2<<endl;

//pvf1=pva1;}valueofpva2is0x000000000x0012FF7C0x0012FF7C0x0012FF740x0012FF74注释去掉会出现编译错误/10/1011北京科技大学计算机系C++大学基础教程第六章第11页例指针定义、赋值与使用#include<iostream.h>voidmain(){ int*i_pointer; //申明int型指针i_pointer inti; //申明int型数i i_pointer=&i; //取i地址赋给i_pointer i=10; //int型数赋初值

cout<<"Outputinti="<<i<<endl;//输出int型数值

cout<<"Outputintpointeri="<<*i_pointer<<endl;

//输出int型指针所指地址内容}/10/1012北京科技大学计算机系C++大学基础教程第六章第12页6.2.2间接引用运算

间接引用运算符“*”是一个一元算符,它和指针变量连用,对指针所指向内存地址单元进行间接访问。使用格式是:

*指针变量假如指针变量iptr指向整型变量va,*iptr就是变量va内容/10/1013北京科技大学计算机系C++大学基础教程第六章第13页

例6.2对变量直接访问和间接访问:写出以下程序运行结果。#include<iostream>usingnamespacestd;voidmain(){charch1='a',*ch;intk1=100;ch=&ch1; //指针ch指向变量ch1cout<<"*ch="<<*ch<<endl; //间接访问*ch='B';cout<<"ch1="<<ch1<<endl; //直接访问

ch1=k1;cout<<"*ch="<<*ch<<endl; //间接访问

}运行结果:*ch=ach1=B*ch=d/10/1014北京科技大学计算机系C++大学基础教程第六章第14页

例6.3定义指向指针指针变量。观察对这种指针变量间接访问结果。#include<iostream>usingnamespacestd;voidmain(){intva=100,*pva,**ppva;//ppva是指向指针指针

intk1=100;pva=&va;cout<<"*pva="<<*pva<<endl; //间接访问结果是整型数

ppva=&pva;cout<<"*ppva="<<*ppva<<endl;//间接访问结果是地址

cout<<"pva="<<pva<<endl; //就是指针pva内容}运行结果:*pva=100*ppva=0x0012FF7Cpva=0x0012FF7C

/10/1015北京科技大学计算机系C++大学基础教程第六章第15页6.2.2间接引用运算/10/1016北京科技大学计算机系C++大学基础教程第六章第16页6.2.3指针算术运算

指针能够进行算术运算只有加法和减法。指针能够和一个整数n做加法或者减法运算。指针p和整数n相加(相减)含义是指向当前指向位置p前方或后方第n个数据地址。/10/1017北京科技大学计算机系C++大学基础教程第六章第17页

例6.4经过指针间接访问,输出下标为偶数数组元素值。#include<iostream>usingnamespacestd;voidmain(){intk1[10]={11,24,37,44,58,66,79,86,93,108},*k;k=&k1[0]; for(inti=0;i<10;i=i+2)

cout<<"k1["<<i<<"]="<<*(k+i)<<"";cout<<endl;}

运行结果:K1[0]=11k1[2]=37….

数组第一个元素(下标为0)地址赋值给指针k

每次循环,指针加2/10/1018北京科技大学计算机系C++大学基础教程第六章第18页6.2.3指针算术运算指针和指针直接加法是没有意义,也是不允许。指针和指针减法是能够进行,其意义是求出两个指针之间能够存放几个指定类型数据。不允许用一个整数减一个指针。/10/1019北京科技大学计算机系C++大学基础教程第六章第19页6.2.4指针关系运算和逻辑运算

相同类型指针能够进行各种关系运算。比较两个指针相等还是不相等。进行指针“大于”、“小于”比较,只是要判定指针在内存中相对位置。指向不一样数据类型指针,指针和普通整数比较是没有意义,也是不允许。惟一能够和指针比较整数是0。经过指针和0比较来判定指针本身是不是空指针。即指针能够和零之间进行等于或不等于关系运算。比如:p==0或p!=0/10/1020北京科技大学计算机系C++大学基础教程第六章第20页6.2.5void类型指针

void类型指针就是“无类型”指针。申明方式以下: void*<指针名>;void类型指针变量中存放也是内存地址,不过不指定这个地址单元内数据类型。/10/1021北京科技大学计算机系C++大学基础教程第六章第21页6.2.5void类型指针

void类型指针使用:任何其它类型指针都能够赋值给void指针。必须注意,这么赋值后void指针类型依然是void。void类型指针不能够直接赋值给任何其它类型指针。不论何时,void指针都不能够经过间接引用来访问内存中数据。要经过void类型指针访问内存数据,必须进行指针类型强制转换,才能够经过指针间接引用访问内存数据。/10/1022北京科技大学计算机系C++大学基础教程第六章第22页

例6.5使用memcpy通用复制函数复制数组。

#include<iostream>usingnamespacestd;#include<string.h>voidmain(){charsrc[10]="012345678";chardest[10];char*pc=(char*)memcpy(dest,src,10);

cout<<pc<<endl;ints1[3]={1,2,3};intd1[3];int*pi=(int*)memcpy(d1,s1,12);

cout<<*pi<<""<<*(pi+1)<<""<<*(pi+2)<<endl;}

运行结果:012345678123

复制字符数据,10个字节复制整型数据,12个字节/10/1023北京科技大学计算机系C++大学基础教程第六章第23页6.2.5void类型指针

void类型指针还有一个详细应用:显示字符指针内容。除了字符指针外,其它指针都能够直接用cout语句来输出地址值。不过,用cout输出字符指针时,则是输出它所指向字符串。能够将字符指针强制转换为void指针,再用cout语句输出,就能够看到地址值。如:char*pch="HelloC++";cout<<pch<<endl;cout<<(void*)pch<<endl;

inta[3]={1,2,3};cout<<a<<endl;cout<<*a<<endl;charc[]=“hello”;cout<<c<<endl;cout<<*c<<endl;cout<<c+1<<endl;/10/1024北京科技大学计算机系C++大学基础教程第六章第24页6.3指针和函数

/10/1025北京科技大学计算机系C++大学基础教程第六章第25页6.3指针和函数在程序设计中,指针有很多应用。其中之一就是用指针作为函数参数,从而形成了C++函数调用中另一个调用方式:地址调用。/10/1026北京科技大学计算机系C++大学基础教程第六章第26页6.3.1指针作为函数参数用指针作为函数参数,实现地址调用,必须满足以下条件:函数形式参数是指针变量;函数实参数是内存地址,详细来说能够是数组名、变量地址、用变量地址初始化指针;形参指针类型和实参地址类型必须相同。/10/1027北京科技大学计算机系C++大学基础教程第六章第27页6.3.1指针作为函数参数满足以上条件后,这么函数调用在使用上有以下特点:实参传递给形参是内存地址,所以形参指针指向实参变量;形参指针经过间接引用,直接访问实参变量,包含改变实参变量值;函数调用后,能够保留对实参变量操作结果,假如有多个实参,就能够有多个实参变量在函数调用中得到修改。/10/1028北京科技大学计算机系C++大学基础教程第六章第28页

例6.6编写数据交换函数。在main中调用这个函数,交换main中定义变量。

#include<iostream>usingnamespacestd;voidSwap(int*a,int*b);voidmain(){ intx(5),y(10);

cout<<"主函数变量值:

x="<<x<<"y="<<y<<endl; Swap(&x,&y); cout<<"返回后变量值:

x="<<x<<"y="<<y<<endl;}voidSwap(int*a,int*b){ intt; t=*a; *a=*b; *b=t;cout<<"函数中完成了交换:*a="<<*a<<"*b="<<*b<<endl;}

运行结果:主函数变量值:x=5y=10函数中完成了交换:*a=10*b=5返回后变量值:

x=10y=5

变量地址作为实参数指针变量作为形式参数函数例子里:#include<iostream.h>void

swap(int

a,int

b);void

main(){int

x(5),y(10);cout<<"x="<<x<<"y="<<y<<endl;swap(x,y);cout<<"x="<<x<<"y="<<y<<endl;}void

swap(int

a,int

b){int

t;t=a;a=b;b=t;}/10/1029北京科技大学计算机系C++大学基础教程第六章第29页6.3.1指针作为函数参数程序中用变量x和y地址作实参,传递给指针a和b,如图6.1(a)。经过间接引用*a和*b进行交换,实际上就是x和y进行交换,如图6.1(b)。

/10/1030北京科技大学计算机系C++大学基础教程第六章第30页

例6.7指针变量指向一个数组。用指针变量作为实参调用一个函数。在函数中指针指向数组第二个元素。观察函数返回后,实参指针值有没有改变。

#include<iostream>usingnamespacestd;voidMove(int*a);voidmain(){ intx[5]={10,20,30,40,50},*px=x; cout<<"调用前*px="<<*px<<endl;

Move(px); cout<<"调用后px"; if(px==x)cout<<"没有改变,*px还是"<<*px<<endl; elsecout<<"也向前移动,*px变为"<<*px<<endl;}voidMove(int*a){ a=a+1;cout<<"函数中完成了指针移动:*a="<<*a<<endl;}

运行结果:调用前*px=10

函数中完成了指针移动:*a=20调用后px没有改变*px还是10

指针作为实参数指针变量作为形式参数/10/1031北京科技大学计算机系C++大学基础教程第六章第31页6.3.2指针指针作为函数参数假如一定要改变实参指针值,能够用指针变量地址作实参,形式参数就应该是指针指针。/10/1032北京科技大学计算机系C++大学基础教程第六章第32页

例6.8修改例6.7,使得实参指针返回后,指向新地址。#include<iostream>usingnamespacestd;voidMove(int**a); voidmain(){ intx[5]={10,20,30,40,50},*px=x; cout<<"调用前*px="<<*px<<endl; Move(&px); cout<<"调用后px"; if(px==x)cout<<"没有改变,*px还是"<<*px<<endl; elsecout<<"也向前移动,*px变为"<<*px<<endl;}voidMove(int**a){ *a=*a+1; cout<<"函数中完成了指针移动:**a="<<**a<<endl; }运行结果:调用前*px=10

函数中完成了指针移动:**a=20调用后px也向前移动,*px变为20

指针地址作为实参数指针指针作为形式参数/10/1033北京科技大学计算机系C++大学基础教程第六章第33页6.3.3传递参数保护:指针和常量经过数组名地址调用,能够改变实参数组内容。不过,并不是全部以数组名作为实参函数调用,都需要改变数组值。比如,在调用一个求数组最大值函数时,就不希望数组值发生改变。希望在函数中能够限制对数组元素修改。使用常指针能够到达这个目标。/10/1034北京科技大学计算机系C++大学基础教程第六章第34页6.3.3传递参数保护:指针和常量常指针是指向常量指针(PointertoConstantdata)习惯说法。就是要求指针所指向内容不能够经过指针间接引用来改变。常指针说明格式是:

const<类型名>*<指针名>;

比如:constint*ptint;指针ptint类型是(constint*),也就是指向一个恒定整型数。/10/1035北京科技大学计算机系C++大学基础教程第六章第35页

例6.10常指针示例。观察以下程序运行。

#include<iostream>usingnamespacestd;voidmain(){intia=10,ib=20;constint*ptint; ptint=&ia; //用ia地址初始化cout<<*ptint<<endl;ptint=&ib; //改变为ib地址ib=ib+100; //ib本身依然能够改变cout<<*ptint<<endl;//*ptint=100; //语句错误:左值是常量}

运行结果:10

120常指针申明注释去掉会出现编译错误/10/1036北京科技大学计算机系C++大学基础教程第六章第36页6.3.3传递参数保护:指针和常量指针常量(Pointerconstant)。指针本身内容是个常量,不能够改变。指针常量申明格式是:

<类型名>*const<指针名>=<初值>;比如: charch,*constptch=&ch;

数组名就是数组首地址。现在能够说:数组名就是一个指针常量。

/10/1037北京科技大学计算机系C++大学基础教程第六章第37页

例6.11指针常量示例。指出以下程序错误。#include<iostream>usingnamespacestd;voidmain()

{inta=10,b=100; int*constpa=&a; //pa是指针常量

cout<<*pa<<endl; *pa=20; //指针常量间接引用是允许

cout<<a<<endl; pa=&b;

constintc=50;// int*constpc=&c; }

错误语句注释掉后运行结果:10

20语句有错:常量不能当左值语句有错,地址类型不一样///10/1038北京科技大学计算机系C++大学基础教程第六章第38页

例6.12用常指针作形参,函数printString能够输出数组内容,不能够对数组修改。

#include<iostream>usingnamespacestd;voidprintString(constchar*);voidmain(){charphrase[]="C++isamodernprogramminglanguage";cout<<"Thestringis:\n";printString(phrase);cout<<endl;}//main函数结束voidprintString(constchar*Ptarray){while(*Ptarray) cout<<*Ptarray++; }不使用常指针也是能够完成打印。不过没有保护了。数组名作实参数常指针作形式参数/10/1039北京科技大学计算机系C++大学基础教程第六章第39页6.3.4指针函数假如一个函数返回值是指针,则这么函数称为指针函数。如:

int*func01(intk);

函数func01返回一个指向整型数据指针。返回指针,实际就是返回一个内存地址。要注意:不能返回函数中局部变量地址。这么地址处于内存堆栈区,是全部函数公用区域。其中数据是不稳定,可能因为其它函数执行而发生改变。/10/1040北京科技大学计算机系C++大学基础教程第六章第40页

例6.13返回不一样地址指针函数。观察运行结果。#include<iostream>usingnamespacestdintva=100; //全局变量int*get_int(int*pt,intj) //指针函数{intvalue=300,*pti=pt;if(j==0||j==1)returnpti;elseif(j==2)returnpti=&value;}voidmain(){int*ptint,vb=200;for(inti=0;i<3;i++) {if(i==0)ptint=get_int(&va,i); elseif(i==1)ptint=get_int(&vb,i); elseif(i==2)ptint=get_int(&va,i); cout<<"i="<<i<<"*ptint="<<*ptint<<endl; }}

运行结果i=0*ptint=100i=1*ptint=200i=2*ptint=-858993460

返回全局变量或者vb地址返回函数局部变量地址/10/1041北京科技大学计算机系C++大学基础教程第六章第41页6.4指针和字符串

/10/1042北京科技大学计算机系C++大学基础教程第六章第42页6.4.1字符串处理两种方式C++字符串常量是用双引号括起字符序列,并以字符‘\0’作为结束标志。如 "Thisisastring"。字符串常量存放在内存某个区域,有自己固定首地址。假如将字符串常量首地址看成是指针,这种指针既是常指针,也是指针常量。/10/1043北京科技大学计算机系C++大学基础教程第六章第43页6.4.1字符串处理两种方式C++处理字符串有两种方式:数组方式和指针方式。数组方式是将字符串存入字符数组后,再进行处理。普通能够在申明数组时候用字符串来初始化:charstring_array[]="aniceday!";指针方式是用字符串常量来初始化一个字符指针:char*string_pt="aniceday!";/10/1044北京科技大学计算机系C++大学基础教程第六章第44页6.4.1字符串处理两种方式常量不能放在等式左边运行时会犯错/10/1045北京科技大学计算机系C++大学基础教程第六章第45页

例6.14strcpy和strncpy比较。#include<iostream>#include<string>usingnamespacestd;voidmain(){intn;char*array1="HappyBirthdaytoYou";chararray3[15];chararray2[25];strcpy(array2,array1); cout<<"Thestringinarray1is:"<<array1<<"\nThestringinarray2is:"<<array2<<'\n';/*strcpy(array3,array1); cout<<array3<<endl;*/n=sizeof(array3);strncpy(array3,array1,n-1);//复制array1n-1个字符到array3array3[14]='\0'; //添加'\0'到array3cout<<"Thestringinarray3is:"<<array3<<endl;}

不包含提醒运行结果HappyBirthdaytoYouHappyBirthdaytoYouHappyBirthday

复制array1到array2,没有问题复制array1到array3,空间不够,有运行错误按实际数组大小,复制array1到array3,没有问题/10/1046北京科技大学计算机系C++大学基础教程第六章第46页6.5经过指针访问数组

/10/1047北京科技大学计算机系C++大学基础教程第六章第47页6.5经过指针访问数组指针和数组有天然联络。因为数组名本身就是地址,也就是某种类型指针。将指针和数组名联络起来,访问数组就多了一个方法。即使一维数组名和二维数组名都是地址,都能够看作是某种指针,不过指针类型是不一样。所以,经过指针访问一维数组和二维数组方法是不一样。

/10/1048北京科技大学计算机系C++大学基础教程第六章第48页6.5.1经过指针访问一维数组要经过指针访问一维数组,必须首先申明一个和数组类型相同指针,而且用数组名来对指针初始化,如:

intA[10],*pa=A;然后,就能够用各种方式访问数组元素:数组名和下标,如A[0]、A[4];指针和下标,如pa[0]、pa[4];指针加偏移量间接引用,如*(pa+4);数组名加偏移量间接引用,如*(A+4);指针自加后间接引用,如*pa++。

/10/1049北京科技大学计算机系C++大学基础教程第六章第49页

例6.15求数组内所存放字符串长度。#include<iostream>usingnamespacestd;voidmain(){charChArray[]="Thisisastring.",*ptch;inti,j,k,offset1,offset2;ptch=ChArray; //指针初始化

for(i=0;ChArray[i]!='\0';i++);cout<<"Thelengthofthestringis:"<<i<<endl;for(j=0;ptch[j]!='\0';j++);cout<<"Thelengthofthestringis:"<<j<<endl;for(offset1=0;*(ChArray+offset1)!='\0';offset1++);cout<<"Thelengthofthestringis:"<<offset1<<endl;

for(offset2=0;*(ptch+offset2)!='\0';offset2++);cout<<"Thelengthofthestringis:"<<offset2<<endl;

for(k=0;*ptch++!='\0';k++);cout<<"Thelengthofthestringis:"<<k<<endl;}

运行结果都相同方式1:数组名和下标方式2:指针和下标方式3:数组名加偏移量间接引用方式4:指针加偏移量间接引用方式5:指针自加间接引用/10/1050北京科技大学计算机系C++大学基础教程第六章第50页

例6.16求整型数组平均值,显示数组元素和平均值。#include<iostream>usingnamespacestd;voidmain(){intintArray[10]={8,11,23,34,45,56,65,78,86,97},*ptint;inti,num,sum;floataverage;ptint=intArray;

sum=0;num=sizeof(intArray)/sizeof(*intArray);

for(i=0;i<num;i++)sum=sum+*ptint++;average=(float)sum/num;ptint=intArray;

cout<<"数组元素是:\n";for(i=0;i<num;i++)cout<<*ptint++<<"";cout<<"\n平均值是:"<<average<<endl;}

数组元素是:8112334455665788697平均值是:50.3

指针初始化求数组元素数目求平均值cout<<*ptint;指针再次初始化输出数组元素和它们平均值/10/1051北京科技大学计算机系C++大学基础教程第六章第51页6.5.2经过指针访问二维数组二维数组能够看成是一维数组一维数组。二维数组名即使也是地址(指针),不过却和一维数组名有不一样类型。对一维数组A[5],数组名A地址,就是数组第一个元素A[0]地址。指针类型是指向数组元素指针。A+1就是元素A[1]地址。/10/1052北京科技大学计算机系C++大学基础教程第六章第52页6.5.2经过指针访问二维数组对二维数组B[3][4],数组名B地址,则是其中第一个一维数组B[0]地址。指针类型是指向一维数组指针。B+1就是下一个一维数组B[1]地址。如图6.3所表示。

/10/1053北京科技大学计算机系C++大学基础教程第六章第53页6.5.2经过指针访问二维数组在定义指向一维数组指针时,还必须指出一维数组大小。申明指向一维数组指针格式以下: <类型名>(*指针变量名)[一维数组大小];

比如,和图6.3中两个二维数组所对应指向一维数组指针定义以下:char(*ptchb)[4],(*ptchc)[2];ptchb=B;ptchc=C;/10/1054北京科技大学计算机系C++大学基础教程第六章第54页6.5.2经过指针访问二维数组对于指向一维数组指针,含有以下特征:

二维数组名是指向一维数组指针,而不是指向数组元素指针。

指向一维数组指针加1结果,是指向下一个一维数组指针。

指向一维数组指针间接引用结果依然是地址,即*ptchb依然是地址。只是地址类型变了。变为一维数组B[0]第一个元素B[0][0]地址。

因为*ptchb是数组元素地址,**ptchb就是数组元素值。用指向一维数组指针访问二维数组第i行第j列元素普通公式是*(*(指针名+i)+j)。

/10/1055北京科技大学计算机系C++大学基础教程第六章第55页

例6.17比较指向一维数组指针和指向数组元素指针。#include<iostream>usingnamespacestd;voidmain(){shortB[3][4],C[3][2];short(*ptshb)[4],(*ptshc)[2];ptshb=B;ptshc=C;cout<<"比较不一样指向一维数组指针差异\n";cout<<"ptshb地址是:"<<ptshb<<"\n";cout<<"ptchb+1地址是:"<<ptshb+1<<"\n";cout<<"ptchc地址是:"<<ptshc<<"\n";cout<<"ptchc+1地址是:"<<ptshc+1<<"\n";

比较不一样指向一维数组指针差异ptshb地址是:0x0012FF68ptchb+1地址是:0x0012FF70ptchc地址是:0x0012FF5Cptchc+1地址是:0x0012FF60

B第0行地址

B第1行地址

C第0行地址

C第1行地址/10/1056北京科技大学计算机系C++大学基础教程第六章第56页

例6.17比较指向一维数组指针和指向数组元素指针。cout<<"不一样类型指针\n";cout<<"ptshb地址是:"<<ptshb<<endl;cout<<"*ptshb地址是:"<<*ptshb<<endl;cout<<"*ptshb+1地址是:"<<*ptshb+1<<endl;cout<<"B[0][1]地址是:"<<&B[0][1]<<endl;//cout<<"ptchb和*ptchb相等吗?"<<(ptchb==*ptchb)<<endl; //有语法错误

cout<<"*ptshb+1和&B[0][1]相等吗?";

if(*ptshb+1==&B[0][1])cout<<"Yes"<<endl;}

不一样类型指针ptshb地址是:0x0012FF68*ptshb地址是:0x0012FF68*ptshb+1地址是:0x0012FF6AB[0][1]地址是:0x0012FF6A*ptshb+1和&B[0][1]相等吗?Yes

B第0行地址

B第0行第0列元素地址

B第0行第1列元素地址

B第0行第1列元素地址/10/1057北京科技大学计算机系C++大学基础教程第六章第57页

例6.18用单循环程序,求二维数组元素平均值。#include<iostream>usingnamespacestd;voidmain(){intdArray[3][4]={32,42,12,25,56,76,46,53,76,89,96,82},(*pt)[4];intsum,j;floataverage;sum=0;pt=dArray;

j=sizeof(dArray)/sizeof(**dArray); for(inti=0;i<j;i++) sum=sum+*(*pt+i);average=(float)sum/j;cout<<"数据平均值等于:"<<average<<endl;}

运行结果:数据平均值等于57.0833指向一维数组指针初始化求数组元素数目,**dArray就是元素dArray[0][0]数组求和求平均值输出平均值/10/1058北京科技大学计算机系C++大学基础教程第六章第58页6.5.3指针数组若数组元素是某种类型指针,这么数组称为指针数组。指针数组申明格式以下:<类型>*<数组名>[常量表示式];比如:char*member_name[10];注意和申明指向一维数组指针差异:char(*member_pointer)[10];

/10/1059北京科技大学计算机系C++大学基础教程第六章第59页6.5.3指针数组指向字符指针:char*member_name[]={"Merry“,"John","Hill"};指向这么指针数组指针:char**arr=member_name;或者:char**arr;arr=member_name;这么定义后,*arr就是指向字符串指针,以下语句 cout<<*arr<<endl;

将显示数组中第一个字符串"Merry"。/10/1060北京科技大学计算机系C++大学基础教程第六章第60页

例6.17比较指向一维数组指针和指向数组元素指针。#include<iostream>usingnamespacestd;voidmain(){shortB[3][4],C[3][2];short(*ptshb)[4],(*ptshc)[2];ptshb=B;ptshc=C;1)cout<<*(*(ptshb+i)+j)

2)short*psh[]for(i=0;i<;i++)psh[i]=B[i];*(psh[i]+j)

33/10/1061北京科技大学计算机系C++大学基础教程第六章第61页

例6.19将若干字符串存入指针数组,并以NULL表示结束。将这些字符串按升序排序,输出排序后字符串。#include<string>#include<iostream>usingnamespacestd;voidPrint(char*[]);voidString_sort(char*[]);voidmain(){char*pn[]={"George","Bill","Wendy","Abraham","Bruce",NULL};//指针数组

String_sort(pn);Print(pn);}

函数原型函数原型指针数组求平均值输出平均值/10/1062北京科技大学计算机系C++大学基础教程第六章第62页

voidString_sort(char*arr[]){char**p1,**p2,*p3;p1=arr;p2=arr+1; while(*(p1+1)!=NULL) {while(*p2!=NULL) {if(strcmp(*p1,*p2)>0) {p3=*p1; *p1=*p2; *p2=p3;} p2++;}

p1++;

p2=p1+1; } }voidPrint(char*arr[]){cout<<"Sortedstringsare:"<<endl; while(*arr!=NULL) {cout<<*arr<<endl;arr++;}}

Sortedstringsare:AbrahamBillBruceGeorgeWendy

逐次取出每个指针和其余每个指针所指字符串比较假如字符串*p1大于*p2交换地址重新设置p2/10/1063北京科技大学计算机系C++大学基础教程第六章第63页6.5.4命令行参数命令行参数是main函数参数。带有命令行参数main函数原型是:<类型>main(intargc,char*argv[]);argc:整数,存放命令行参数数目。argv[]:指针数组,存放所输入命令行参数。其中argv[0]是所执行程序名,argv[argc-1]是最终一个输入参数字符串,argv[argc]中自动存入NULL,表示输入结束。/10/1064北京科技大学计算机系C++大学基础教程第六章第64页

例6.20显示命令行参数程序。

#include<iostream>usingnamespacestd;voidmain(intargc,char*argv[]){cout<<"Thecommandlineargumentsare:\n";for(inti=0;i<argc;++i)cout<<argv[i]<<'';}从第0个到第argc-1个参数显示参数原工程文件名称为:test,编译链接形成可执行文件:test.exe输入testhelloeveryone,输出为:Thecommandlineargumentsare:testhelloeveryone/10/1065北京科技大学计算机系C++大学基础教程第六章第65页

例6.21对命令行输入字符串进行排序并输出排序结果。

#include<string>#include<conio.h>#include<iostream>usingnamespacestd;voidPrint(char*[]);voidString_sort(char*[]);voidmain(intargc,char*argv[]){String_sort(argv+1);Print(argv+1);getche();}如在命令行输入:E:\myfile\proj01\debug\proj01.exebcdabcaabbbd回车后运行并显示:Sortedstringsare:aababcbbdbcd从第1个参数开始排序/10/1066北京科技大学计算机系C++大学基础教程第六章第66页6.6指针访问动态内存/10/1067北京科技大学计算机系C++大学基础教程第六章第67页6.6指针访问动态内存

动态内存是在程序执行时才能够申请、使用和释放内存。也就是存放动态数据内存区域。存放动态数据区域称为“堆”,动态内存也称为堆内存。动态内存不能经过变量名来使用,而只能经过指针来使用。/10/1068北京科技大学计算机系C++大学基础教程第六章第68页6.6.1动态内存申请和释放C++中经过运算符new申请动态内存,运算符delete释放动态内存。动态内存申请运算符new使用格式:

new<类型名>(初值)运算结果:假如申请成功,返回指定类型内存地址;假如申请失败,返回NULL指针。动态内存使用完成后,要用delete运算来释放。delete运算符使用格式:

delete<指针名>;

/10/1069北京科技大学计算机系C++大学基础教程第六章第69页6.6.2动态数组空间申请和释放申请动态一维数组时,要在new表示式中加上申请数组大小:new<类型名>[常量表示式];注意:在动态申请数组空间时,不能够对数组进行初始化。也能够申请二维数组空间:int(*pi_marray)[4];pi_marray=newint[3][4];释放动态数组空间都用相同表示式:delete[]<指针名>;

/10/1070北京科技大学计算机系C++大学基础教程第六章第70页6.6.3内存泄漏和指针悬挂

内存泄漏是指动态申请内存空间,没有正常释放,不过也不能继续使用情况。如:char*ch1;ch1=newchar('A');char*ch2=newchar;ch1=ch2;原来为ch1所申请存放字符A空间就不可能再使用了,产生了内存泄漏。/10/1071北京科技大学计算机系C++大学基础教程第六章第71页6.6.3内存泄漏和指针悬挂让指针指向一个已经释放空间,即所谓指针悬挂(Dangling)。如:char*ch1,*ch2;ch1=newchar;ch2=ch1;*ch2='B';deletech1;指针ch2就是指向了一个已经释放地址空间,形成指针悬挂。假如还要用deletech2;语句来释放ch2所指向空间,就会出现运行错误。/10/1072北京科技大学计算机系C++大学基础教程第六章第72页6.7引用概念/10/1073北京科技大学计算机系C++大学基础教程第六章第73页6.7引用概念引用(Reference)是C++中新引入概念,也是C语言中不存在数据类型。

引用是变量或者其它编程实体(如对象)别名。所以,引用是不能够单独定义。如图6.4(a)所表示,变量A在内存中有自己地址,而A引用B实际上就是变量A,只是A另外一个名字。

/10/1074北京科技大学计算机系C++大学基础教程第六章第74页6.7.1引用申明和使用引用是经过运算符&来定义,定义格式以下:

<类型名>&引用名=变量名;其中变量名必须是已经定义,而且和引用类型必须相同。比如:

intsomeInt; int&refInt=someInt;必须注意:引用必须在申明时候就完成初始化,不能够先申明引用,然后再用另一个语句对它初始化。

/10/1075北京科技大学计算机系C++大学基础教程第六章第75页6.7.1引用申明和使用引用有以下特点:引用不能独立存在,它只是其它变量别名;引用必须在申明同时就初始化;引用一旦定义,引用关系就不能够更改,即B若是A引用,就不可能是其它变量引用;引用类型就是相关变量类型,引用使用和变量使用相同。/10/1076北京科技大学计算机系C++大学基础教程第六章第76页

例6.22引用使用。观察以下程序结果。

#include<iostream>usingnamespacestd;voidmain(){intintA=10;int&refA=intA;cout<<"引用值和相关变量值相同:refA="<<refA<<endl;refA=5;cout<<"引用改变,则相关变量也改变:intA="<<intA<<endl;cout<<"引用地址和相关变量地址相同:intA地址="<<&intA<<endl;cout<<"引用地址和相关变量地址相同:refA地址="<<&refA<<endl;}引用值和相关变量值相同:refA=10引用改变,则相关变量也改变:intA=5引用地址和相关变量地址相同:intA地址=0x0012FF7C引用地址和相关变量地址相同:refA地址=0x0012FF7C/10/1077北京科技大学计算机系C++大学基础教程第六章第77页6.7.1常引用假如不希望经过引用来改变相关变量值,则能够定义常引用。常引用定义格式:

const<类型名>&引用名=变量名;比如:intsomeInt=10;constint&const

温馨提示

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

评论

0/150

提交评论