版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、2022-4-241第六章 指针和引用 指针(Pointer)是C+和C的一种数据类型。很多其他高级语言也有类似的数据类型。 引用(Reference)则是C+所特有的一种数据类型。 指针和引用在概念上和使用上都有相似之处,但是也有重要的差别。2022-4-24-2-第六章第六章 指针和引用指针和引用6.1 指针的概念6.2 指针的运算6.3 指针访问动态内存6.4 指向结构体的指针6.5 引用概念6.6 指针和引用作为函数的参数6.7 指针和引用作为函数的返回值6.8 指针和字符串6.9 通过指针访问数组2022-4-246.1 指针的概念2022-4-2442022-4-246.1.1 指
2、针和指针变量指针和指针变量 指针是变量的地址。或者说是在内存中,存放某种类型变量的地址。 例如,定义了整型变量a,a的地址就是一个指针。 存放指针的变量就是指针变量。2022-4-246.1.1 指针和指针变量指针和指针变量 当声明了一个指针变量后,确定了三件事: 变量本身在内存中所分配的地址和字节数,指针变量总是占有4个字节; 系统允许的地址范围,以及地址单元内可以存放的内容; 指针变量可以进行的运算。 访问指针变量时,只能看到地址。只有通过这个地址,才能访问地址单元中的内容。这样的访问称为对于内存单元的间接访问。2022-4-24-7-6.1.2 指针变量的声明和初始化指针变量的声明和初始
3、化 指针变量声明的格式是: *变量名1, *变量名2; 例如: int *va1, *va2; char *ch1, *ch2; 指针变量在声明后,变量的值(地址)是随机的。这样的指针变量是不能安全的使用的。因为其中的随机地址完全可能不是有效的数据地址。 2022-4-246.1.2 指针变量的声明和初始化指针变量的声明和初始化 在声明指针变量时的“*”,有两个含义: 声明变量va1、va2、ch1、ch2都是指针变量; 说明变量va1和va2的类型是(int *)型,即指向整型变量的指针。va1和va2所指定的地址单元中,只能存放整型数据。类似地,ch1和ch2的类型是(char *)型,它
4、们所指定的地址单元中,只能存放字符。 指针变量都是有类型的,指针变量的类型就是它所指定的地址单元中存放的数据的类型。 2022-4-24-9-6.1.2 指针变量的声明和初始化指针变量的声明和初始化 指针变量的初始化有两种方法:在声明时的初始化和声明后的初始化。 声明指针变量时就进行初始化的格式是: *指针变量名=&变量名; 其中的变量名应该是已经声明或定义的同类型变量名。例如:char ch1=Y, ch2=A;char *pch1=&ch1, *pch2=&ch2;2022-4-246.1.2 指针变量的声明和初始化指针变量的声明和初始化 也可以在声明指针变量后,用
5、赋值的方式对它们进行初始化。例如:int i1=Y, i2=A;int *pi1, *pi2;pi1=&i1;pi2=&i2; 没有初始化指针变量是不可以使用的。编译带有这样的指针变量的程序,编译系统会给出警告,而运行时会出现错误。 6.2 6.2 指针的运算指针的运算 2022-4-24-11-6.2 指针的运算指针的运算 表6.1 指针的运算2022-4-242022-4-246.2.1 指针的赋值运算指针的赋值运算 指针的赋值运算一定是地址的赋值。用来对指针变量赋值的可以是: 同类型变量的地址; 同类型的已经初始化的指针变量; 其他同类型的指针。 此外,也可以用0或者NU
6、LL对指针变量赋值。使得变量包含的是“空指针”,即不指向任何的内存物理地址。 必须注意:不同类型的指针是不可以互相赋值的。在指针赋值时,不存在类型自动转换的机制。 例6.1 观察以下指针赋值运算的结果。如果将注释去掉,结果将如何?#include using namespace std;void main()int va1=100,*pva1; float vf1=A,*pvf1,*pvf2; int *pva2=NULL; coutvalue of pva2 is pva2endl; pva1=&va1; pvf1=pvf2=&vf1; coutpva1 &va1en
7、dl; coutpvf1 pvf2endl; /pvf1=pva1;value of pva2 is 0 x000000000 x0012FF7C 0 x0012FF7C0 x0012FF74 0 x0012FF74 注释去掉会出现编译错误注释去掉会出现编译错误2022-4-24-15-6.2.2 间接访问运算间接访问运算 间接访问运算符“*”是一种一元算符,它和指针变量连用,对指针所指向的内存地址单元进行间接访问。使用的格式是: *指针变量 如果指针变量iptr指向整型变量va,*iptr就是变量va的内容 2022-4-24-16- 例6.2 对变量的直接访问和间接访问:写出以下程序运行结
8、果。#include using namespace std; void main() char ch1=a,*ch; int k1=100; ch=&ch1; /指针ch指向变量ch1 cout*ch=*chendl;/间接访问 *ch=B; coutch1=ch1endl;/直接访问 ch1=k1; cout*ch=*chendl; /间接访问 运行结果运行结果:*ch=ach1=B*ch=d2022-4-24-17- 例6.3 定义指向指针的指针变量。观察对这种指针变量间接访问的结果。#include using namespace std;void main( ) int va
9、=100,*pva,*ppva; /ppva是指向指针的指针 int k1=100; pva=&va; cout*pva=*pvaendl; /间接访问结果是整型数 ppva=&pva; cout*ppva=*ppvaendl; /间接访问结果是地址 coutpva=pvaendl; /就是指针pva的内容运行结果运行结果:*pva=100*ppva=0 x0012FF7C pva=0 x0012FF7C 2022-4-24-18-6.2.2 间接访问运算间接访问运算2022-4-24-19-6.2.3 指针的算术运算指针的算术运算 指针可以进行的算术运算只有加法和减法。指针可
10、以和一个整数n做加法或者减法运算。指针指针p p和整数和整数n n相加相加( (相相减减) )的含义是指向当前的含义是指向当前指向位置指向位置p p的前方或后的前方或后方第方第n n个数据的地址。个数据的地址。2022-4-24-20- 例6.3 通过指针的间接访问,输出下标为偶数的数组元素的值。#include using namespace std;void main() int k110=11,24,37,44,58,66,79,86,93,108,*k; k=&k10; for(int i=0;i10;i=i+2) coutk1i=*(k+i) ; coutendl; 运行结果
11、运行结果:K10=11 k12=37. 数组第一个元素(下标为数组第一个元素(下标为0)的地址赋值给指针)的地址赋值给指针k 每次循环,指针加每次循环,指针加2 22022-4-24-21-6.2.3 指针的算术运算指针的算术运算 指针和指针的直接加法是没有意义的,也是不允许的。 指针和指针的减法是可以进行的,其意义是求出两个指针之间可以存放几个指定类型的数据。 不允许用一个整数减一个指针。 相同类型的指针可以进行各种关系运算。比较两个指针相等还是不相等。 进行指针“大于”、“小于”的比较,只是要判定指针在内存中的相对位置。 指针和一般的整数比较是没有意义的,也是不允许的。惟一可以和指针比较的
12、整数是0。通过指针和0的比较来判定指针本身是不是空指针。 2022-4-246.2.4指针的关系运算和逻辑运算指针的关系运算和逻辑运算 2022-4-24-23-6.2.5 void类型指针类型指针 void类型的指针就是“无类型”指针。声明的方式如下: void *; void类型的指针变量中存放的也是内存的地址,但是不指定这个地址单元内的数据的类型。 2022-4-246.2.5 void类型指针类型指针 void类型的指针的使用: 任何其他类型的指针都可以赋值给void指针。必须注意,这样赋值后的void指针的类型仍然是void。 void类型指针不可以直接赋值给任何其他类型的指针。 无
13、论何时,void指针都不可以通过间接引用来访问内存中的数据。 要通过void类型指针访问内存的数据,必须进行指针类型的强制转换,才可以通过指针间接引用访问内存数据。 2022-4-24void类型指针类型指针 void类型指针还有一个具体的应用:显示字符指针的内容。除了字符指针外,其他指针都可以直接用cout语句来输出地址值。但是,用cout输出字符指针时,则是输出它所指向的字符串。可以将字符指针强制转换为void指针,再用cout语句输出,就可以看到地址值。如:char *pch=Hello C+;coutpchendl;cout(void*)pchendl; 2022-4-24-26- 例
14、6.4 使用memcpy通用复制函数复制数组。 #include using namespace std; #include void main() char src10=012345678; char dest10; char* pc=(char*)memcpy(dest,src,10); cout pc endl; int s13=1,2,3; int d13; int *pi=(int*)memcpy(d1,s1,12); cout*pi *(pi+1) *(pi+2)endl; 运行结果运行结果:0123456780123456781 2 3 复制字符数据,复制字符数据,1010个字节
15、个字节复制整型数据,复制整型数据,1212个字节个字节2022-4-24-27-6.2.6 指针类型转换指针类型转换 实际应用的指针变量都是有类型的,指针类型就是指针所指的地址空间所存放的数据的类型。 除了void指针,不同类型的指针是不可以自动类型转换的,也就不能进行赋值运算。在例6-1中的语句pvf1=pva1(整型指针赋值给float指针)就是有语法错误的语句。 除了void指针,指针类型不仅不能自动转换,也不能进行强制类型转换。若pch是字符指针,p是double类型指针,以下的语句: pch=static_cast(p);在编译时有语法错误:“不能将double*转换为char*”,
16、也就是说指针的强制类型转换也是不允许的。但是,如果使用C风格的类型转换:pch=(char*)p;在编译时没有语法错误,仅在执行时有问题。所以,还是要使用static_cast来进行强制类型转换。唯一允许的是void指针和其它指针类型之间的转换2022-4-24-28-指针类型转换指针类型转换#include using namespace std;void main() float f=1.0; float* fPtr=&f; /浮点指针 void* fv=&f;int* iPtr=static_cast(fv); /浮点变量地址赋给整型指针 cout f endl iPtr
17、: iPtr *iPtr hex*iPtrendl fPtr: fPtr *fPtr endl ;2022-4-24/例6-5利用格式控制符hex可以显示整数的机器数的程序6.3 6.3 指针访问动态内存指针访问动态内存2022-4-24-30-指针访问动态内存指针访问动态内存 动态内存是在程序执行时才可以申请、使用和释放的内存。也就是存放动态数据的内存区域。存放动态数据的区域称为“堆”,动态内存也称为堆内存。 动态内存不能通过变量名来使用,而只能通过指针来使用。 2022-4-24-31-2022-4-246.3.1 动态内存的申请和释放动态内存的申请和释放 C+中通过运算符new申请动态内
18、存,运算符delete释放动态内存。 动态内存申请运算符new的使用格式: new (初值) 运算的结果:如果申请成功,返回指定类型内存的地址;如果申请失败,返回NULL指针。 动态内存使用完毕后,要用delete运算来释放。delete运算符使用格式: delete ; 2022-4-246.3.2 动态数组空间的申请和释放动态数组空间的申请和释放 申请动态一维数组时,要在new表达式中加上申请数组的大小: new 常量表达式 ; 注意:在动态申请数组空间时,不可以对数组进行初始化。 释放动态数组空间都用相同的表达式: delete ; 2022-4-24-34-6.3.3 内存泄漏和指针悬
19、挂内存泄漏和指针悬挂 内存泄漏是指动态申请的内存空间,没有正常释放,但是也不能继续使用的情况。如: char *ch1;ch1 = new char(A);char *ch2 = new char;ch1=ch2; 原来为ch1所申请的存放字符A的空间就不可能再使用了,产生了内存泄漏。 2022-4-246.3.3 内存泄漏和指针悬挂内存泄漏和指针悬挂 让指针指向一个已经释放的空间,即所谓的指针悬挂(Dangling)。如: char *ch1, *ch2;ch1 = new char;ch2 = ch1;*ch2 = B;delete ch1; 指针ch2就是指向了一个已经释放的地址空间,形
20、成指针悬挂。如果还要用delete ch2;语句来释放ch2所指向的空间,就会出现运行错误。 6.4 6.4 指向结构体的指针指向结构体的指针2022-4-24-36- 指向结构体的指针指向结构体的指针 定义变量时,我们可以定义指向int型的指针变量,类似的,可以有指向新定义的结构型数据类型的指针变量。 声明了指向结构的指针后,必须对指针初始化。现在我们知道对于指针的初始化有两种方法:其一是用已经定义的变量地址来初始化,其二是用new申请一个地址来对指针赋值。 2022-4-24-37-具体对结构指针来说:(1)可以将结构变量的地址赋给结构指针,使用取地址“&”操作,得到结构变量的地址
21、,这个地址就是结构的第一个成员的地址。例如:struct student /声明新的数据类型 long num;/学号 char name20; /姓名 float score;/成绩;student stu=20041118,Li Li“, 18; /定义结构变量并初始化student * ps=&stu; /定义结构指针并初始化(2)使用new操作在堆中给结构指针分配空间。例如:student * ps=new student;/定义结构指针用动态地址初始化用结构指针访问结构成员时,用箭头操作符代替原来的点操作符对结构体成员进行操作。比如,把学生的成绩输出显示,语句如下:couts
22、core;其中,ps-score等价于(*ps).score。2022-4-24解:说明:每个员工的信息包括姓名、工作证号、薪水,定义为结构类型。定义结构指针并让它的指向确定,通过结构指针访问结构成员,输出显示员工的信息。/例6-6 结构指针的定义和使用#include #include using namespace std;struct Employee char name20; unsigned long id; float salary;2022-4-24例6-6 结构指针的定义和使用。void main() Employee pr1; Employee* prPtr; prPtr=&
23、amp;pr1; strcpy(prPtr-name,zhang san); prPtr-id=98001; prPtr-salary=3350.0; cout name id salary endl;程序运行结果:zhang san 98001 33502022-4-246.5 6.5 引用概念引用概念2022-4-24-42-2022-4-24-43-引用概念引用概念 引用(Reference)是C+中新引入的概念,也是C语言中不存在的数据类型。 引用是变量或者其他编程实体(如对象)的别名。因此,引用是不可以单独定义的。如图6.4(a)所示,变量A在内存中有自己的地址,而A的引用B实际上就
24、是变量A,只是A的另外一个名字。 2022-4-24-44-6.5.1 引用的声明引用的声明 引用是通过运算符&来定义的,定义的格式如下: &引用名 = 变量名; 其中的变量名必须是已经定义的,并且和引用的类型必须相同。例如: int someInt;int &refInt = someInt; 必须注意:引用必须在声明的时候就完成初始化,不可以先声明引用,然后再用另一个语句对它初始化。 2022-4-24-45-引用有以下的特点: 引用不能独立存在,它只是其他变量的别名; 引用必须在声明的同时就初始化; 引用一旦定义,引用关系就不可以更改,即B若是A的引用,就不可能是
25、其他变量的引用; 引用的类型就是相关的变量的类型,引用的使用和变量的使用相同。 例6-7 引用的使用。观察以下程序的结果。 #include using namespace std;void main() int intA=10; int& refA=intA; cout引用的值和相关变量值相同:refA=refAendl; refA=5; cout引用的变化,则相关变量也变化:intA=intAendl; cout引用的地址和相关变量地址相同:intA的地址&intAendl; cout引用的地址和相关变量地址相同:refA的地址&refAendl;2022-4-24
26、运行结果:引用的值和相关变量值相同:refA=10引用的变化,则相关变量也变化:intA=5引用的地址和相关变量地址相同:intA的地址0 x0012FF7C引用的地址和相关变量地址相同:refA的地址0 x0012FF7C6.66.6指针和引用作为函数的指针和引用作为函数的参数参数2022-4-24 在程序设计中,指针有很多应用。其中之一就是用指针作为函数的参数,从而形成了C+函数调用中的另一种调用方式:地址调用。 2022-4-24指针和函数指针和函数 用指针作为函数参数,实现地址调用,必须满足以下条件: 函数的形式参数是指针变量; 函数的实参数是内存的地址,具体来说可以是数组名、变量的地
27、址、用变量地址初始化的指针; 形参指针类型和实参地址类型必须相同。 2022-4-246.6.1 指针作为函数的参数指针作为函数的参数 满足以上条件后,这样的函数调用在使用上有以下的特点: 实参传递给形参的是内存的地址,所以形参指针指向实参变量; 形参指针通过间接引用,直接访问实参变量,包括改变实参变量的值; 函数调用后,可以保留对实参变量的操作结果,如果有多个实参,就可以有多个实参变量在函数调用中得到修改。 2022-4-246.6.1 指针作为函数的参数指针作为函数的参数2022-4-24 例6.8 编写数据交换的函数。在main中调用这个函数,交换main中定义的变量。 #include
28、using namespace std;void Swap(int *a, int *b);void main() int x(5), y(10); cout主函数变量的值: x=x y=yendl;Swap(&x,&y);cout返回后变量的值: x=x y=yendl;void Swap(int *a, int *b) int t;t=*a;*a=*b;*b=t; cout函数中完成了交换:*a=*a *b=*bendl; 运行结果运行结果:主函数变量的值:主函数变量的值:x=5 y=10函数中完成了交换:函数中完成了交换:*a=10 *b=5返回后变量的值:返回后变量的值
29、: x=10 y=5 变量的地址作为实参数变量的地址作为实参数指针变量作为形式参数指针变量作为形式参数 程序中用变量x和y的地址作实参,传递给指针a和b,如图6.1(a)。通过间接引用*a和*b进行交换,实际上就是x和y进行交换,如图6.1(b)。 2022-4-246.6.1 指针作为函数的参数指针作为函数的参数2022-4-246.6.2 引用作为函数参数引用作为函数参数 引用使用最多的场合是作为函数的形式参数。 引用作为函数的形式参数具有以下的特点: 引用作为形式参数时,实参数是相同类型的变量; 引用作为形式参数,参数传递属于地址传递; 引用作为形式参数时,在函数中并不产生实参数的副本,
30、形式参数的引用和实参数的变量实际上是同一个实体; 函数对引用的操作,也是对实参变量的操作,函数调用可以改变实参数的值。 例6.9 用引用作为形式参数,通过函数调用,交换两个实参数。 #include using namespace std;void swap_1(int &x, int &y)/引用作为形式参数 int j; j=x; x=y; y=j;void main() int a=12345, b=54321; cout 函数调用前:a= a b=bendl; swap_1(a, b);/变量作为实参数 cout 函数调用后:a= a b=bendl; 2022-4-2
31、4 函数调用前:函数调用前:a= 12345 b=54321a= 12345 b=54321 函数调用后:函数调用后:a= 54321 b=12345a= 54321 b=123452022-4-246.6.2 引用作为函数参数引用作为函数参数 使用引用作为形式参数还需要注意: 如果实参数需要保护,可以使用“常引用”作为形式参数; 用引用作形参和用变量作形参是有区别的,但是,对于这两种情况,实参数可能相同。例如,函数swap(int a, int b)和swap(int &a, int&b)看起来是两个可以区分的重载函数。但是,都可以用整型变量x和y来调用:swap(x, y)
32、,因此,实际上是不可区分的,函数swap(int a, int b)和swap(int &a, int&b)不是可以区分的重载函数。 2022-4-246.6.3 常指针常指针常指针是指向常量的指针(Pointer to Constant data)的习惯说法。就是规定指针所指向的内容不可以通过指针的间接访问来改变。 常指针说明的格式是: const *; 例如: const int *ptint; 指针ptint的类型是(const int *),也就是指向一个恒定的整型数。 2022-4-24 例6.10 常指针示例。观察以下程序的运行。 #include using na
33、mespace std;void main()int ia=10, ib=20;const int *ptint; ptint=&ia;/用ia地址初始化cout*ptintendl;ptint=&ib;/改变为ib的地址ib=ib+100;/ib本身仍然可以改变cout*ptintendl;/*ptint=100;/语句错误:左值是常量 运行结果运行结果:10 120 常指针声明常指针声明注释去掉会出现编译错误注释去掉会出现编译错误2022-4-246.6.4 指针的指针作为函数的参指针的指针作为函数的参数数 如果一定要改变实参指针的值,可以用指针变量的地址作实参,形式参数就
34、应该是指针的指针。 2022-4-24 例6.12 指针变量指向一个数组。用指针变量作为实参调用一个函数。在函数中指针指向数组的第二个元素。观察函数返回后,实参指针值有无变化。 #includeusing namespace std;void Move(int *a);void main() int x5=10,20,30,40,50, *px=x;cout调用前的*px=*pxendl; Move(px);cout调用后的px;if(px=x)cout没有变化,*px还是*pxendl;else cout也向前移动,*px变为*pxendl;void Move(int *a) a=a+1;
35、cout函数中完成了指针移动:*a=*aendl; 运行结果运行结果:调用前的调用前的*px=10 函数中完成了指针移动:函数中完成了指针移动:*a=20 调用后的调用后的pxpx没有变化没有变化*px还是还是10 指针作为实参数指针作为实参数指针变量作为形式参数指针变量作为形式参数 例6.13修改例6.12,使得实参指针返回后,指向新的地址。 #includeusing namespace std;void Move(int *a);void main()int x5=10,20,30,40,50, *px=x;cout调用前的*px=*pxendl;Move(&px); cout调
36、用后的px;if(px=x)cout没有变化,*px还是*pxendl;else cout也向前移动,*px变为*pxendl;void Move(int *a)*a=*a+1; cout函数中完成了指针移动:*a=*aendl; 2022-4-24 运行结果运行结果:调用前的调用前的*px=10 函数中完成了指针移动:函数中完成了指针移动:*a=20 调用后的调用后的px也向前移动,也向前移动,*px变为变为20 指针的地址作为实参数指针的地址作为实参数指针的指针作为形式参数指针的指针作为形式参数6.76.7指针和引用作为函数的指针和引用作为函数的返回值返回值2022-4-24-61-202
37、2-4-246.7.1 指针函数指针函数 如果一个函数的返回值是指针,则这样的函数称为指针函数。如: int *func01(int k); 函数func01返回一个指向整型数据的指针。 返回指针,实际就是返回一个内存的地址。 要注意:不能返回函数中局部变量的地址。这样的地址处于内存的栈区,是所有函数公用的区域。其中的数据是不稳定的,可能因为其他函数的执行而发生改变。 2022-4-24 例6-15 一个指针函数完成一个数组的倒序。源数组由函数参数传递,倒序后的数组地址由指针函数返回。 #include using namespace std;int * reverse(int const *
38、 list, const int size)/指针函数 int result6;/函数中定义的局部数组 for (int i = 0, j = size - 1; i size; i+, j-) resultj = listi; return result;/返回局部数组的地址void printArray(int const *list, const int size) for (int i = 0; i size; i+) cout listi ;void main() int list = 1, 2, 3, 4, 5, 6; int *pList = reverse(list, 6);
39、/获得倒序后数组的地址 printArray(pList, 6);/显示倒序后的数组程序运行结果:-858993460 -858993460 -858993460 -858993460 -858993460 5 结果完全不对。原因就在于指针函数返回的是函数局部数组的地址。 2022-4-24 例6-16 对例6-15的修改。只要修改指针函数reverse。可以在函数这申请一个动态数组的地址,最后返回这个地址就可以。注意不要忘了用delete来释放这个地址。#include using namespace std;int * reverse(int const * list, const int
40、 size)/指针函数 int *result = new intsize; /函数中定义的动态数组 for (int i = 0, j = size - 1; i size; i+, j-) resultj = listi; return result; /返回动态数组的地址2022-4-24 void printArray(int const *list, const int size) for (int i = 0; i size; i+) cout listi ;void main() int list = 1, 2, 3, 4, 5, 6; int *pList = reverse(
41、list, 6);/获得倒序后数组的地址 printArray(pList, 6);/显示倒序后的数组 delete pList;程序运行结果:6 5 4 3 2 12022-4-246.7.2 引用作为函数的返回值引用作为函数的返回值返回引用有以下需要注意的地方: 返回引用需要在函数的返回值类型中加以说明,形式为: &函数名(形式参数表) 返回引用的返回语句就是:return 变量名; 返回引用实际是返回地址。在使用上,或者直接使用这个地址;或者使用这个地址单元的数据。 返回的引用可以作为左值继续操作,而返回的变量值是不可以继续运算的。这是返回引用和返回变量值在使用上的主要区别。 2
42、022-4-24 /例6-17 引用作为函数的返回值#include #include using namespace std;struct personchar name15; int contribution; double bonus;/定义结构体person p1=Li Li,500,0,p2=Zhao Zhao,600,0; /两名职工是全局变量person& compare( )/返回引用的函数 if(p1.contributionp2.contribution) return p1; else return p2;2022-4-24 例6.17引用作为函数返回值。 voi
43、d main() compare().bonus=1000;/返回值作为左值直接操作 coutsetw(10) p1.contribution p1.bonusendl; coutsetw(10) p2.contribution p2.bonusendl;程序运行结果: Li Li 500 0 Zhao Zhao 600 10006.8 6.8 指针和字符串指针和字符串 2022-4-24-70-2022-4-246.8.1 字符串处理的两种方式字符串处理的两种方式C+字符串常量是用双引号括起的字符序列,并以字符0作为结束标志。如This is a string。
44、字符串常量存放在内存的某个区域,有自己固定的首地址。 如果将字符串常量的首地址看成是指针,这种指针既是常指针,也是指针常量。 2022-4-246.8.1 字符串处理的两种方式字符串处理的两种方式C+处理字符串有两种方式:数组方式和指针方式。 数组方式是将字符串存入字符数组后,再进行处理。一般可以在声明数组的时候用字符串来初始化: char string_array=Whats a nice day!; 指针方式是用字符串常量来初始化一个字符指针: char *string_pt=Whats a nice day!; 2022-4-246.8.1 字符串处理的两种方式字符串处理的两种方式常量不
45、能放在等常量不能放在等式左边式左边运行时会出错运行时会出错2022-4-246.8.2 字符串操作函数字符串操作函数 调用这些函数时,原则上可以使用字符数组名、已经初始化的字符指针作为实调用这些函数时,原则上可以使用字符数组名、已经初始化的字符指针作为实参数。字符串常量还可以作为源字符串的实参数。参数。字符串常量还可以作为源字符串的实参数。 目的串必须是可写的。目的串必须是可写的。 例6.18 strcpy和strncpy的比较。 #include #include using namespace std;void main() int n; char *array1 = Happy Birt
46、hday to You; char array3 15 ; char array2 25 ; strcpy( array2, array1 ); cout The string in array1 is: array1 nThe string in array2 is: array2 n; /*strcpy(array3,array1); coutarray3endl; */ n=sizeof(array3); strncpy( array3, array1, n-1 ); / 复制array1的n-1个字符到array3 array3 14 = 0; / 添加0 到array3 cout T
47、he string in array3 is: array3 endl; 2022-4-24 不包括提示的运行结果不包括提示的运行结果Happy Birthday to YouHappy Birthday to YouHappy Birthday 复制复制array1array1到到array2array2,没有问题没有问题复制复制array1array1到到array3array3,空间不够,空间不够,有运行错误有运行错误按实际数组大小,按实际数组大小,复制复制array1array1到到array3array3,没有问题没有问题6.9 6.9 通过指针访问数组通过指针访问数组 2022-4
48、-242022-4-24通过指针访问数组通过指针访问数组 指针和数组有天然的联系。因为数组名本身就是地址,也就是某种类型的指针。将指针和数组名联系起来,访问数组就多了一种方法。 虽然一维数组名和二维数组名都是地址,都可以看作是某种指针,但是指针的类型是不同的。因此,通过指针访问一维数组和二维数组的方法是不同的。 2022-4-246.9.1 通过指针访问一维数组通过指针访问一维数组 要通过指针访问一维数组,必须首先声明一个和数组类型相同的指针,并且用数组名来对指针初始化,如: int A10, *pa=A; 然后,就可以用多种方式访问数组元素: 数组名和下标,如A0、A4; 指针和下标,如pa
49、0、pa4; 指针加偏移量的间接访问,如*(pa+4); 数组名加偏移量的间接访问,如*(A+4); 指针自加后的间接访问,如*pa+。 2022-4-24 例6.19 求数组内所存放的字符串的长度。 #include using namespace std;void main() char ChArray=This is a string.,*ptch; int i,j,k,offset1,offset2; ptch=ChArray;/指针初始化 for(i=0;ChArrayi!=0;i+); coutThe length of the string is:iendl; for(j=0;p
50、tchj!=0;j+); coutThe length of the string is:jendl; for(offset1=0;*(ChArray+offset1)!=0;offset1+); coutThe length of the string is:offset1endl; for(offset2=0;*(ptch+offset2)!=0;offset2+); coutThe length of the string is:offset2endl; for(k=0;*ptch+!=0;k+); coutThe length of the string is:kendl; 运行结果运行结果都相同都相同方式方式1 1:数组名和下数组名和下标标方式方式2 2:指针和下:指针和下标标方式方式3 3: 数组名加数组名加偏移量的间接引用偏移量的间接引用方式方式4 4:指针加偏:指针加偏移量的间接引用移量的间接引用方式方式5 5:指针自加:指针自加的间接引用的间接引用 例6.20 求整型数组的平均值,显示数组元素和平均值。 #include using namespace std;void main() int intArray10=8,11,23,34,45,56,65,78,
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2024-2030年中国橱柜拉篮行业需求情况与营销前景预测报告
- 电线电缆在冷链物流中的应用考核试卷
- 2024-2030年中国柴油机火前针阀体项目可行性研究报告
- 2024-2030年中国柴油机排气管项目可行性研究报告
- 2024-2030年中国条码无线扫描枪行业供需趋势及投资策略研究报告
- 2024-2030年中国智慧水务行业发展规划及项目融资模式分析报告
- 2024-2030年中国方向盘锁行业供需预测及发展策略分析报告
- 2024-2030年中国新式茶饮行业运营情况及营销策略分析报告
- 2024年运维支持服务协议范本
- 2024至2030年超市购物篮项目投资价值分析报告
- 《 大学生军事理论教程》全套教学课件
- 《骆驼祥子》读书分享
- 《常见的天气系统》教案范例
- 人教版数学小升初衔接练习+解析(统计与概率)
- 泵房施工合同范例
- JT-T-1238-2019半柔性混合料用水泥基灌浆材料
- DZ∕T 0173-2022 大地电磁测深法技术规程
- HYT 116-2008 蒸馏法海水淡化蒸汽喷射装置通 用技术要求(正式版)
- 2024保密知识竞赛题库(完整版)
- 人体常见病智慧树知到期末考试答案章节答案2024年
- 2024年4月自考06962工程造价确定与控制试题
评论
0/150
提交评论