第6章 指针Word格式文档下载.docx
- 文档编号:16349706
- 上传时间:2022-11-23
- 格式:DOCX
- 页数:34
- 大小:99.09KB
第6章 指针Word格式文档下载.docx
《第6章 指针Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《第6章 指针Word格式文档下载.docx(34页珍藏版)》请在冰豆网上搜索。
//数组ppBuffer是用来保存5个char型变量的地址的指针型数组
void*pAddress;
//pAddress是一个void*型指针型变量
void*型指针是很特殊的一种指针,它不像int*、float*等指针那样,指向的内存单元中保存的是具体的一种数据类型的变量,void*只是一个地址,这个地址中保存的可能是int型变量的起始地址,也可能是f1oat型变量的起始地址,也可能什么都不是。
C++语言中定义了一个符号常数NULL,用来代表空指针值。
所谓空指针值是人为规定的一个数值,用来表示“无效”的指针值。
在VisualC++中,NULL被定义为0。
6.2.2指针的基本操作
与指针有关的基本运算符有以下两个。
(1) &
变量名。
&
为取地址运算符,用来获取变量的首地址。
(2)*指针变量名。
*为指向运算符,用来获取指针变量所指向变量的值。
和*运算符都是单目运算符,其优先级高于所有双目运算符,采用从右到左的结合性。
例如:
inti=5,j,*pint;
//定义整型变量i、j;
同时定义整型指针变量phint
phint=&
i:
//将i的指针(即首地址)赋给phint,使phnti指向i
j=*phint;
//将phint所指变量i的值(5)赋给变量j
说明:
①指针变量是有类型的。
②要注意第1句和第3句中*phint的区别:
第1句是指针变量定义语句,其中的*表示phint是一个指针类型变量;
第3句其中的*表示取出指针变量phint的值(即phint所指内存单元中的内容)。
6.2.3指针变量的初始化与引用
与其它变量一样,指针变量也可以在定义时对其赋初值(即指针变量的初始化)。
这里要注意的是,所赋的初值必须是所定义数据类型的变量地址。
如果没有具体明确的变量地址要被赋值,可以先赋以NULL。
【例6-1】指针变量的使用例题。
#include<
iostream.h>
voidmain( )
{
intm,n,*p1=&
m,*p2=&
n,*phint=NULL;
m=n=6;
cout<
"
*p1="
*p1<
,*p2="
*p2<
endl;
p1="
p1<
,p2="
p2<
m="
m<
,n="
n<
phint="
phint<
*p1+=3;
p2=p1;
*p2*=4;
phint=p2;
}
程序运行结果为
*p1=6,*p2=6
p1=0x0012FF7C,p2=0x0012FF78
m=6,n=6
pjint=0x00000000
*p1=36,*p2=36
p1=0x0012FF7C,p2=0x0012FF7C
m=36,n=6
pjint=0x0012FF7C
特殊的void*型指针由于没有任何一种数据类型同它对应,要将其它的任何一种指针值赋予void*型指针变量都必须通过强制类型转换。
void*nPointer;
int*pnValue;
nPointer=(void*)pnValue;
2.指针的算术运算
对于非void*型的指针型变量,只能进行加一个整数、减一个整数和两个指针变量相减三种运算。
void*型指针变量不能做任何算术运算。
intnValue;
int*pPointer1=&
nValue,*pPointer2;
pPointer2=pPointer1+1;
假设pPointer1的初始地址是0x20000000,则进行pPointer2=pPointer1+1;
运算后,pPointer2的地址值是0x20000004,如图6-2所示。
对于指针的自加(++)与自减(--)运算,显然很好理解,即
相当于:
pPointer2=pPointer1++;
注意:
两个指针不能相加。
3.指针的关系运算
指针间也可以进行关系运算。
关系运算符>
、<
、==、>
=、<
=、!
=可以用来连接两个指针型变量做关系运算。
指针间的关系运算结果就是两个指针所指的地址值的大小的关系运算结果。
由于内存地址是线性编码的,所以,如果一个变量m的保存位置在变量n之前,则&
n就等于1,&
m>
n就等于0。
两个进行关系运算的指针一般要求是同一类型的
指针。
4.常指针(const修饰符与指针)
const也可以与指针一起使用。
它们的组合情况较复杂,可简单归纳为三种:
指向常量的指针、常指针和指向常量的常指针。
(1)指向常量的指针
指向常量的指针是指一个指向常量的指针变量,指针可更新,但指针所指的数据不可修改,例如:
constchar*name="
chen"
;
//声明指向字符常量的指针变量
name[3]='
a'
//错误,即name所指的数据不可修改
name="
zhang"
//合法,指针可更新
(2)常指针
常指针是指把指针本身,而不是它指向的对象声明为常量。
创建一个常指针,就是创建一个不能移动的固定指针,但是它所指的数据可以改变。
char*constname="
//常指针
//合法
name="
;
//出错
(3)指向常量的常指针
指向常量的常指针是指这个指针本身不能改变,它所指向的数据值也不能改变。
constchar*constname="
//指向常量的常指针
//出错,不能改变指针所指的值
//出错,不能改变指针本身
5.引用型变量
关于引用的声明在1.2.4节中已介绍过,这里,我们再通过以下例题来看看引用与目标变量之间的关系。
【例6-2】引用的声明和使用例题。
inti,j=4,&
ri=i;
//定义ri为整型变量i的引用
i=3;
cout<
i="
i<
,ri="
ri<
i的地址是"
,ri的地址是"
ri+=5;
cout<
,ri="
ri=j;
,j="
j<
,j的地址是"
ri=&
j;
//出错
删除最后一句出错的语句后,程序的运行结果为
i=3,ri=3
i的地址是0x0012FF7C,ri的地址是0x0012FF7C
i=8,ri=8
i的地址是0x0012FF7C,ri的地址是0x0012FF7C
i=4,ri=4,j=4
i的地址是0x0012FF7C,ri的地址是0x0012FF7C,j的地址是0x0012DD78
6.3指针与数组
指针与数组之间有着密切的联系。
实际上,C++语言对数组的操作完全是通过指针来进行的。
6.3.1指针与数组的关系
数组的实质是内存中一块连续的空间,存储着同一类型变量的数据。
实际上,C++语言就是这样对数组元素进行访问的。
在声明一个数组时,C++语言将在内存中开辟两个空间,一个用于保存数组元素,另一个用于保存数组的第1个元素的地址。
数组名就是用于保存数组第1个元素的地址的指针型常量。
通过保存数组第1个元素地址的数组名这个指针型常量,可以使用“[]”运算符访问数组元素,也可以直接使用指针的运算规则访问数组元素。
intpnArray[10];
nValue=*pnArray;
//nValue等于prlArray的第1个元素的值
nValue=pnArray[5];
//nValue等于pnArray的第6个元素的值
nValue=*(pnArray+5);
//与上一句nValue=pnArray[5]等价
同样,对于指针型变量也可以使用“[]”运算符,将其作为数组来使用。
如有
int*pnPointer=pnArray;
//数组名pnArray本身是指针型,因此不必用取地址运算符&
则以下3条语句等价:
nValue=pnPointer[5];
nValue=*(pnPointer+5);
指针与数组之间的区别:
指针型变量是变量,是可以不断赋值的;
而数组名虽然是指针,但它是一指针型常量,只能指向固定的内存地址,不能将一个指针值赋予一个数组名。
以下语句在C++语言中是错误的:
charcArray[10];
charch;
cArray=&
ch;
//错误,不允许将一个指针值赋予数组名
6.3.2通过指针引用数组元素
由于指针同数组的特殊关系,我们已经看到,数组与指针几乎可以互换使用,下面利用一个具体例子来说明通过指针引用数组元素的方法。
【例6-3】用指针的方法编写求一个数组中所有元素之和的程序。
分析:
此函数的参数可以写成指针型。
由于数组名的实质就是指针,在调用该函数时,只要将数组名作为实际参数传递给函数即可。
程序代码如下:
intSum(int*pPointer,intn)
intnSum=0;
while(n>
0)
{
nSum+=*pPointer++;
n--;
}
returnnSum;
intpnArray[10]={6,7,8,9,5,4,3,2,10,1};
数组各元素和:
sum1="
Sum(pnArray,10)<
数组各元素之和:
sum1=55
需要注意的是,在main( )中调用Sum函数时,实际参数pnArray与形式参数pPointer尽管是指针类型,但它们间仍然是赋值关系,在Sum中对形式参数pPointer进行的加法运算不会影响到Sum函数以外的指针型常量(数组名)pnArray的值。
但由于pPointer与pnArray的值相同,也就是说它们指向同一个地址,所以在函数内如果对pPointer所指向的地址中保存的值进行更改操作时,在函数外的pnArray如果访问这个地址会得到被Sum更改后的值。
上例中可以将语句nSum+=*pPointer++替换成nSum+=pPointer[10-n],或者将语句intSum(int*pPointer,intn)替换成intSum(intpPointer[],intn),程序运行结果都完全一样。
【例6-4】用指针的方法编写将数组各元素进行排序的函数程序。
voidCompositor(int*pPointer,intn)
inti,j,t,p;
for(i=0;
n-1;
i++)
p=i;
for(j=i+1;
n;
j++)
{
if(*(pPointer+p)<
=*(pPointer+j))p=j;
}
t=*(pPointer+i);
*(pPointer+i)=*(pPointer+p);
*(pPointer+p)=t;
inti;
Compositor(pnArray,10);
排序后的数组为:
10;
cout<
"
pnArray[i]<
排序后的数组如下:
10,9,8,7,6,5,4,3,2,1
6.3.3指向多维数组的指针
如定义一维数组
inta[10],*pa=a;
则一维数组a中的任何一个元素:
a[i]等同于*(a+i)
如定义二维数组
intfMatrix[3][4],*pPointer=&
fMatrix[0][0];
则二维数组fMatrix中的任何一个元素:
fMatrix[m][n]等同于*(pPointer+m*4+n)
对二维数组fMatrix[3][4]中关于一维数组名fMatrix[m](0<
3)所代表的含义:
fMatrix[0]等于&
fMatrix[0][0]
fMatrix[1]等于&
fMatrix[1][0]
fMatrix[2]等于&
fMatrix[2][0]
fMatrix[m][n]等同于*(fMatrix[m]+n)
二维数组名fMatrix的含义:
fMatrix等于&
fMatrix[0]
fMatrix[m][n]等同于*(*(fMatrix+m)+n)
fMatrix的数据类型不是int*,而是int**。
【例6-5】用指针的方法操作二维数组,并输出相应的指针值(地址),注意观察和比较一级指针和二级指针。
voidmain()
staticintaMatrix[3][4]={{1,2,3,4},{2,3,4,5},{5,4,3,2}};
inti,j,*p;
//使用二维数组的行地址(一级指针)
使用二维数组的行地址(一级指针)输出数组:
3;
p=aMatrix[i];
for(j=0;
4;
cout<
*(p+j);
//使用二维数组名(二级指针)
使用二维数组名(二级指针)输出数组:
*(*(aMatrix+i)+j);
相应的指针值:
二维数组名"
行地址"
数组元素地址"
aMatrix<
aMatrix[0]<
aMatrix[0][0]<
指针+1后的值:
aMatrix+1<
aMatrix[0]+1<
aMatrix[0][0]+1<
各行首地址:
aMatrix[i]<
1234
2345
5432
输出相应的指针值(以下地址值根据系统运行情况而定):
二维数组名行地址数组元素地址
0x0012FF500x0012FF500x0012FF50
0x0012FF600x0012FF540x0012FF54
0x0012FF50
0x0012FF60
0x0012FF70
【例6-6】用指针的方法将二维数组转置(行列互换),并输出结果。
intaMatrix[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
转置前的矩阵:
//p存放各行的起始地址
转置后的矩阵:
for(j=0;
for(i=0;
p=aMatrix[i];
//p存放各行的起始地址(注意所在的位置)
5678
9101112
159
2610
3711
4812
6.3.4指针数组与多级指针
1.指针数组
声明指针型变量的形式如下:
*指针数组名[数组长度]
int*ppArray[5];
//声明一个保存5个int*型元素的指针数组
char*ppString[6];
//声明一个保存6个char*型元素的指针数组
2.多级指针
多级指针一般又称为指针的指针。
定义二级指针变量的一般形式如下:
**二级指针变量名
例如,二维数组名就是一个典型的二级指针。
intaMatrix[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
int**pp=aMatrix;
//编译可以通过,执行时,内存错误,可以直接用aMatrix作二级指针。
6.4指针与函数
6.4.1指针变量作为函数参数
指针类型也可以作为函数的参数。
通过指针型参数,可以将一个变量的地址传递给函数,而通过这个地址,函数体中的语句就可以修改函数以外的变量的值。
【例6-7】用传送地址的方法实现变量a和b的内容交换。
voidchangFunction(int*,int*);
//函数声明语句,参数为指针类型
inta=5,b=10;
函数调用前:
a="
a<
b="
b<
changFunction(&
a,&
b);
//以a、b的地址为实参调用函数
函数调用后:
voidchangFunction(int*m,int*n)
inttemp;
//互换用的变量
temp=*m;
*m=*n;
*n=temp;
函数中参数:
*m="
*m<
*n="
*n<
a=5,b=10
*m=10,*n=5
a=10,b=5
6.4.2指针作为函数的返回类型
返回值是地址的函数称为指针函数,其定义的一般形式如下:
*函数名(形参表)
函数体
说明:
函数返回的指针应是非函数内部的局部变量的地址(因为函数内部局部变量的存储单元,当函数结束返回时将被释放)或者是NULL。
【例6-8】函数的返回值是指针类型例题。
#include<
char*f(char*ps)
*ps='
B'
returnps;
voidmain()
charstr='
A'
*f(&
str)<
//注意:
str)中的“*”
B
6.4.3指向函数的指针
同数据一样,程序也是保存在内存中的。
CPU在执行程序时,首先需要找到程序的入口(开始)地址,然后从内存中取出指令并逐条执行。
函数的指针是一个函数在内存中的入口地址。
在调用一个函数时,系统从当前的位置跳到该函数的入口地址处执行指令;
函数返回时,系统回到刚才调用函数的那条指令的位置继续执行程序。
我们定义一个指针变量,并赋予它函数名,这样该指针变量的内容就是该函数在内存的入口地址。
这样的指针变量称为指向函数的指针变量,简称函数指针变量。
由此,我们就可以通过函数指针变量来调用它所指向的函数。
1.函数指针变量的定义与使用
声明一个函数指针变量的形式如下:
(*函数指针变量名)(参数表)
注意,定义中的两对圆括
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 第6章 指针