Visual C++ 面向对象与可视化程序设计 : Visual C++ 面向对象与可视化程序设计 谷慧娟
hjgu@gist.edu.cn
指针 : 指针 本书的重点及难点之一
正确地使用指针,能使程序简洁、高效
不正确地使用指针,容易导致程序运行时错误,甚至导致系统崩溃 Visual C++ 面向对象与可视化程序设计
Slide 3 : 指针和指针变量
指针和数组
指针数组和指向指针的指针变量
指针和函数 Visual C++ 面向对象与可视化程序设计
指针和指针变量 : 指针和指针变量 指针的概念
说明一个变量时,编译程序要为该变量分配一个连续的内存单元。为了区分不同的内存单元,必须给每一个内存单元指定一个唯一的编号,这个编号称为内存单元的地址。与“旅客住店问题”类似,这个内存单元的地址是唯一的,不可改变的;地址里面的变量的值是可以经常改变的。 Visual C++ 面向对象与可视化程序设计 旅客住店问题,当一个旅客住在一个旅馆时,只要知道其房间号码,就能找到该旅客;房间号码是唯一的,是不可改变的,但是房间内的乘客是可以经常改变的
指针和指针变量 : 指针和指针变量 指针的概念
设有说明语句: 20001:
char c1=‘a’;
float x=50.5; 20004:
系统为变量c1和x分配内存单元单元,设分配的内存单元分别为20001和20004
在编译或执行期间,为每一个变量分配的内存单元的编号(地址)称为变量的地址,也称为变量的指针,简称指针,即指针是一个内存单元的地址
在变量的地址中的内容称为变量的值,即指针的内容
定义一个变量用来存放一个内存单元的地址(指针)时,这个变量称为指针变量,即指针变量的值是另一个变量的地址 Visual C++ 面向对象与可视化程序设计 a 50.5
指针和指针变量 : 指针和指针变量 指针变量的说明
说明指针变量的一般格式:
类型 *变量名1,*变量名2,…,*变量名n;
其中,类型指的是指针变量所指向的数据类型,即指针所指向的内存单元中存放的数据类型
“*”表示所说明的变量是指针变量 Visual C++ 面向对象与可视化程序设计 int *p1,*p2,i,j;
float *p3,*p4,x,y;
char *pc,c;
指针和指针变量 : 指针和指针变量 注意:
1)指针变量的值只能是某一个变量的地址(起始地址),在说明指针变量时,通常其值是不确定的,只有对指针变量赋值后才能使用它
2)编译程序也要为指针变量分配内存单元,因为指针变量的值是一个地址,其取值范围是不变的,通常用四个字节来表示地址值,所以为不同类型的指针变量所分配的内存单元的大小是相同的
3)在说明指针变量的同时可以进行初始化
“&”称为取地址运算符,用于取其操作数的地址 Visual C++ 面向对象与可视化程序设计 int i;
int *p1=&i;
指针和指针变量 : 指针和指针变量 指针的运算(三种)
赋值运算
关系运算
算术运算 Visual C++ 面向对象与可视化程序设计
指针和指针变量 : 指针和指针变量 赋值运算
1.可以将与指针变量同类型的任一变量的地址赋给一个指针变量
2.同类型的指针变量间可以相互赋值
3.取内容运算符“*”,运算结果为取其操作数所指向的内存单元的
值(变量的值)
4.可将0赋给任一指针变量,其含义是初始化指针变量,使其值为
空,即该指针不指向任一变量。
5.向一个未初始化的指针变量所指向的内容赋值是极其危险的,并
且也是不被允许的。 Visual C++ 面向对象与可视化程序设计 int i=100,*p;
p=&i;
cout<<*p; #include
void main()
{ int *p;
cin>>*p;
cout<<*p<<'\n';}
指针和指针变量 : 指针和指针变量 Visual C++ 面向对象与可视化程序设计 #include
void main()
{
int a1=100,*p1,*p2;
p1=&a1;
p2=p1;
cout<<"*p1="<<*p1<<'\t'<<"*p2="<<*p2<指针和指针变量 : 指针和指针变量 算术运算
实际使用中,主要对指针进行加或减的运算。
C++中,同一个说明语句中所说明的变量,均分配在同一个连续的内存空间,但分配的顺序随不同的编译器而异,有些系统从左到右分配,有些则从右到左,VC++按后一种方式分配。以上程序,在不同的编译环境下,执行的结果可能不同。 Visual C++ 面向对象与可视化程序设计 #include
void main()
{
int i=10,j=20,k=30;
int *p1=&j;
cout<<"*p1="<<*p1<<'\t'<<"p1="<指针和指针变量 : 指针和指针变量 Visual C++ 面向对象与可视化程序设计 #include
void main()
{
int a[10]={100,200,300,400,500};
int *p=&a[0];
cout<<"*p="<<*p<<'\t'<<"p="<指针和指针变量 : 指针和指针变量 关系运算
两个指针变量的关系运算是根据两个指针变量值的大小来进行比较的,通常只有同类型的指针变量进行比较才有意义。 Visual C++ 面向对象与可视化程序设计 #include
void main()
{ int a[5]={100,200,300,400,500},sum=0;
int *p1,*p2;
for(p2=&a[0];p2<=&a[4];p2++)
{ cout<<*p2<<'\t'; }
p1=&a[0]+5;
p2=&a[0];
while(p2!=p1)
{ sum+=*p2;
p2++;}
cout <<'\n' <<"元素的和为:"<指针和指针变量 : 指针和指针变量 特别注意几种运算符的混合运算及其优先级 Visual C++ 面向对象与可视化程序设计 int a[5]={100,200,300,400,500},*p1=&a[0],b;
求下列表达式的结果
1)&*p1
2)*&a[0]
3)*(p1++)
求出b的结果
4)b=*p1++
5)b=*++p1
6)b=(*p1)++
7)b=++*p1
(各表达式独立,无上下承接关系)
指针和数组 : 指针和数组 可用指针访问数组中的任一元素
数组的起始地址叫做数组的指针,指向数组元素的指针变量称为指向数组的指针变量
数组名可以作为一个指针来使用,它的值为整个数组的起始地址,即数组的第0个元素的起始地址。
等价于:
但数组名不同于指针变量,编译程序要为指针变量分配内存空间,而编译程序并不为数组名分配内存空和间,因此,程序中可把数组名作为指针来使用,但不能对数组名进行赋值、“++”和“--”运算。 Visual C++ 面向对象与可视化程序设计 int a[10],*p;
p=&a[0]; int a[10],*p;
p=a;
指针和数组 : 指针和数组 一维数组与指针 Visual C++ 面向对象与可视化程序设计 #include
void main()
{ int a[3],i,*point;
point=&a[0];
//为数组元素赋值
for(i=0;i<3;i++)
{ *point=i;
point++;}
//输出数组所有元素
point=a;
for(i=0;i<3;i++)
{cout<<"a["<指针和数组 : 指针和数组 本例的知识点
1.数组名等同于数组的第0个元素的地址,也是整个数组的起始地址
2.使point指向数组a的第0个元素后,则point+i等同于a+i,其值为a[i]的地址,或者说是数组第i个元素的指针
3.使point指向数组a的第0个元素后,则*(point+i)、*(a+i)、a[i]、point[i]和*&a[i]彼此等同,都表示元素a[i] Visual C++ 面向对象与可视化程序设计
指针和数组(选修) : 指针和数组(选修) 多维数组(以二维为例)与指针
对二维数组,需要掌握的概念:
整个数组的指针(起始地址)
每一行的指针
某一个元素的指针(某行某列的指针)
例如: Visual C++ 面向对象与可视化程序设计 int a[3][3]={{1,2,3},{4,5,6},{7,8,9}};
指针和数组(选修) : 指针和数组(选修) Visual C++ 面向对象与可视化程序设计
指针和数组(选修) : 指针和数组(选修) a[i]和&a[i]都表示地址,且值相同,但意义上不同:
a[i]表示数组第i行第0列元素的起始地址
&a[i]表示数组第i行的起始地址
因为编译器不为数组名a和a[i]分配内存空间,只有为某一变量分配内存空间后,变量名前的&才表示取地址运算符,所以a[i]前是否加&,是用来区分元素地址和行地址的。
*(a+i)与a+i的值相同,但意义也不同:
*(a+i)表示数组第i行第0列元素的起始地址
a+i表示数组第i行的起始地址
这里的*并不表示由a+i指针值所指向的内容,而是用于区分元素地址和行地址的
[思考]&a[i]+j表示的意义 Visual C++ 面向对象与可视化程序设计 int a[3][3],*p1,*p2;
p1=a[i]; //正确
p2=&a[i]; //错误 元素
指针
指针和字符串 : 指针和字符串 由于字符串是存放在数组中的,对字符数组中的字符逐个处理时,前面介绍的指针与数组之间的关系完全适用于字符数组。当使用指向字符的指针来处理字符串时,并不关心存放字符串的数组的大小,而只关心是否到了字符串的结束字符。 Visual C++ 面向对象与可视化程序设计 #include
#include
void main()
{
char s1[]="I am a student!";
char *s2="You are a student!";
char s3[30],s4[40],s5[30];
int i;
char *p1=s3,*p2=s1;
for(;*p1++=*p2++;); for(i=0;i<=strlen(s1);i++)
{
s4[i]=s1[i];
}
strcpy(s5,s2);
cout<<"s3="<指针和字符串 : 指针和字符串 字符型指针变量与字符数组都可用来处理字符串,但使用上有区别:
1)两者概念上不一样
对数组s1,系统将分配16个字节的内存空间
对指针变量s2仅分配4个字节,存放一个内存单元的地址
2)尽管赋初值的形式类同,但含义不一样
对字符数组,是把字符串送到为数组分配的存储空间去
对字符型指针,是先把字符串存放到内存中,然后将存放字符串的起
始地址送到指针变量中
3)对字符数组,可直接输入字符串(cin、cin.getline或逐个输入)
对字符型指针变量,在给此变量赋初值前,不允许将输入的字符串送
到指针变量所指向的内存区域 Visual C++ 面向对象与可视化程序设计
指针和字符串 : 指针和字符串 4)赋值方式不一样
对字符数组,必须逐个元素赋值或通过拷贝的形式赋值
对字符型指针,可将任意指针值赋给字符指针变量
5)程序执行期间,字符数组的起始地址是不能改变的,而字符指针的值
是可以改变的 Visual C++ 面向对象与可视化程序设计 p2=s1+5; //正确
p1=p1+5; //正确
s1=s1+5; //错误 //错误
s3=s1;
s4="I am a student!"; //正确
p2=s1;
p1="I am a student!";
行指针(选修) : 行指针(选修) 定义行指针格式:
int (*p)[4]; //定义了一个行指针p
1.(*p)表明p是一个指针变量,再与[4]结合,表示该指针变量所指向的数据是一个一维数组,该数组由4个元素组成
2.P的值是一个一维数组的行指针,它的值是该一维数组的起始地址(注意:p不能指向该一维数组中的第j个元素)
3.指针变量所指向的一维数组的元素个数应与二维数组的列数相同 Visual C++ 面向对象与可视化程序设计 int a[3][4],*p1,(*p2)[4];
p1=a[i]; //正确
p1=&a[i]; //错误
p2=a[i]; //错误
p2=&a[i]; //正确 元素指针 行指针 类型(*指针名)[常量表达式];
行指针(选修) : 行指针(选修) Visual C++ 面向对象与可视化程序设计 #include
void main()
{
int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}},i;
int (*p)[4];
for(i=0;i<3;i++)
{
p=&a[i];
cout<<(*p)[0]<<'\t'<<(*p)[1]<<'\t'<<(*p)[2]<<'\t'<<(*p)[3]<<'\n';
}
}
指针数组 : 指针数组 由若干个同类型的指针所组成的数组称为指针数组。
格式:
p[0] p[1] p[2] p[3] Visual C++ 面向对象与可视化程序设计 类型 *数组名[常量表达式]; int *p[4];
/*将p定义为一个指针数组,它由4个元素组成,每一个元素所指向的数据类型均为整型*/
指针数组 : 指针数组 Visual C++ 面向对象与可视化程序设计 #include
void main()
{
float a[]={100,200,300,400,500};
float *p[]={&a[0],&a[1],&a[2],&a[3],&a[4]};
int i;
for(i=0;i<5;i++)
{
cout<<*p[i]<<'\t';
}
cout<指向指针的指针变量 : 指向指针的指针变量 p1是指向变量的指针变量,简称一级指针
p2是指向一级指针的指针变量,简称二级指针
p3是指向二级指针的指针变量,简称三级指针
…… Visual C++ 面向对象与可视化程序设计 p3: p2: p1: i:10 int *p1; int **p2; int ***p3;
指向指针的指针变量 : 指向指针的指针变量 Visual C++ 面向对象与可视化程序设计 #include
void main()
{
int i=10;
int *p1,**p2,***p3;
p1=&i;
p2=&p1;
p3=&p2;
cout<指针和函数 : 指针和函数 指针作为函数的参数
将指针作为函数的参数时,传递给函数的是某个变量的地址——传地址
函数的参数为指针时,可将指针值和指针所指向的数据作为函数的输入参数,即在函数体内可使用指针值和指针所指向的数据值;因此,调用函数后,实参指针所指向的数据也随之改变。
数组名作为函数的参数时,作用与指针相同
1.函数的形参为数组,调用函数时的实参为数组名
2.形参为指针变量,实参用数组名
3.形参为数组名,实参为指针
4.形参和实参都是指针变量 Visual C++ 面向对象与可视化程序设计
指针作为函数的参数 : 指针作为函数的参数 Visual C++ 面向对象与可视化程序设计 #include
void change(int *p1,int *p2)
{
int i;
i=*p1;
*p1=*p2;
*p2=i;
}
void main()
{
int a,b;
cout<<"输入两个整数分别赋值给a和b:"<>a>>b;
change(&a,&b);
cout<<"交换后a和b的值分别为:"<函数返回值为指针的函数 : 函数返回值为指针的函数 通过return语句,返回函数返回值:
1)返回一个值(至多且只能返回一个值)
2)返回一个指针
格式 Visual C++ 面向对象与可视化程序设计 类型 * 函数名(形参列表)
{
函数体
}
函数返回值为指针的函数 : 函数返回值为指针的函数 Visual C++ 面向对象与可视化程序设计 #include
char * flip(char *ptr)
{
char *p1,*p2,temp;
p1=p2=ptr;
while(*p2++);
p2-=2;
while(p1指向函数的指针 : 指向函数的指针 一个函数的入口地址称为函数的指针,一个指针变量的值为一个函数的入口地址时,称其为指向函数的指针变量
定义指针函数的指针变量的格式
说明:“类型”是函数返回值的类型;参数列表可以只有参数的类型说明 Visual C++ 面向对象与可视化程序设计 类型 (* 变量名)(参数列表); float (* p1)(void);
float (* p2)(float,float);
指向函数的指针 : 指向函数的指针 函数名表示该函数的入口地址(内存中的起始地址),可将函数名赋给指向函数的指针变量;但是,要求指向函数的指针变量只能指向与该指针变量具有相同返回值和相同参数(个数及顺序一致)的任一函数
对指向函数的指针变量进行赋值后,可用该指针变量来调用函数
格式: 或 Visual C++ 面向对象与可视化程序设计 //定义指向函数的指针
float (* p1)(void);
float (* p2)(float,float);
//声明函数
float f1(float);
float f2(float,float);
//对指针赋值
p1=f1; //错误
p2=f2; //正确 (* 指针变量名)(实参列表) 指针变量名 (实参列表)
指向函数的指针 : 指向函数的指针 Visual C++ 面向对象与可视化程序设计 #include
float add(float x,float y)
{ cout<>a>>c>>b;
switch(c)
{ case '+':p=add;break;
case '-':p=sub;break;
case '*':p=mul;break;
case '/':p=dev;break;
default:cout<<"输入格式不对!\n";}
cout<new和delete运算符 : new和delete运算符 p=new float[n];
表示通过new运算符动态地分配一个有n个元素的实型数组,并使p指向该数组
C++中,new和delete运算符分别用于为指针变量动态分配内存空间个动态收回指针所指向的内存空间 Visual C++ 面向对象与可视化程序设计 int n;
cin>>n;
float a[n];
//错误 int n;
cin>>n;
float *p;
p=new float[n];
//正确
new运算符 : new运算符 使用new运算符为指针变量动态地分配内存空间,格式:
分配由类型确定大小的一片连续的内存空间,并把所分配内存空间的起始地址送给指针变量。若分配不成功,指针变量的值为0
除完成第一种格式的功能外,还能将value的值作为所分配的内存空间的初始化值(对此格式,要求类型只能是基本数据类型)
分配指定类型的数组空间 Visual C++ 面向对象与可视化程序设计 指针变量=new 类型; 指针变量=new 类型(value); 指针变量=new 类型[表达式]; 注意:“类型”与指针变量的类型应相同
delete运算符 : delete运算符 在程序中,用new动态分配内存空间后,若没有用delete释放相应的内存空间,程序执行结束后,系统仍不能利用这部分空间,直到重起计算机。因此,用delete释放已动态分配到的内存空间是程序设计者的职责
delete运算符用来将动态分配到的内存空间归还给系统,格式: Visual C++ 面向对象与可视化程序设计 delete 指针变量; delete []指针变量; delete [表达式]指针变量;
new和delete运算符 : new和delete运算符 Visual C++ 面向对象与可视化程序设计 #include
void main()
{ int n,i,*p,*p1,sum=0;
cin>>n;
p=new int[n];
p1=p;
for(i=0;i上机作业 : 上机作业 用一个函数实现两个字符串的比较,即自己写一个strcmp函数,函数原型为:
int strcmp(char*p1, char *p2);
设p1指向字符串s1,p2指向字符串s2,要求当s1=s2时,函数返回值为0,如果s1>s2,则输出正值;如果s1