220 likes | 340 Views
第六章 指针. C++ 语言程序设计. 本讲内容提要:. 指针概念 指针的定义及使用 指针与数组 指针与函数. 内存. …. 地址 1000H 3000H. a. 5. …. …. 构造数据类型. 6.1 指针的概念. 内存中变量的地址 程序与数据都被存储在存储器的 存储单元 中。 可以通过 变量的名或地址 来访问变量的值。 编译器进行变量名与地址的转换。 例如: int a=5;. 内存. …. 地址 1000H 3000H. 5. a. …. p. …. 6.1 指针的概念. 指针的概念 什么是指针?
E N D
C++语言程序设计 本讲内容提要: • 指针概念 • 指针的定义及使用 • 指针与数组 • 指针与函数
内存 … 地址 1000H 3000H a 5 … … 构造数据类型 6.1指针的概念 • 内存中变量的地址 • 程序与数据都被存储在存储器的存储单元中。 • 可以通过变量的名或地址来访问变量的值。 • 编译器进行变量名与地址的转换。 • 例如: int a=5;
内存 … 地址 1000H 3000H 5 a … p … 6.1指针的概念 • 指针的概念 • 什么是指针? • 是一种特殊的数据类型(地址) • 具有指针类型的变量称为指针变量,也简称为指针。 • 指针变量是用来存放其他变量的地址。 • 指针变量的类型由它所指向变量的类型决定。 • int a=5,*p;p=&a; 1000
内存 … 地址 1000H 3000H 5 a … p … 构造数据类型 6.2指针的定义及使用 • 指针变量的定义与使用 • 其定义的一般形式为: 类型标识符号 *指针变量名 int a=5; int *p=&a; cout<<*p;*p=3; • 说明: • 类型为指针所指变量的类型。 • 指针定义时,‘*’表示该变量为指针变量。 • 指针变量使用时,‘*’为指针所指向的变量的值。
构造数据类型 例6.1 • 指针变量的赋值 • 直接地址赋值 • 例如: • int m=0; • int *p; • p=&m; • 间接地址赋值 • 例如: • int m=0; • int *p,**q; • p=&m; • q=&p; 例6.1 分析程序的输出结果。 #include <iostream.h> void main( ) { int i=0; int *p; p=&i; cout<<*p<<endl; cout<<p<<endl; *p=*p+1; cout<<i<<endl; cout<<*p<<endl; cout<<p<<endl; }
构造数据类型 使用指针变量的注意事项: • 其使用方法和普通变量的使用原理一致,但要注意: • 指针变量内只能存放变量的地址,而不能直接存放一个普通的数。 • 例如:int *p; p=3; • 一个指针变量只能指向同一个类型的变量。 • 例如:int *p;int a=5;float b=6.7; p=&b; • 一个指针变量只有先指向某一个变量后,才可利用该指针变量对它所指向的变量进行操作(间接访问)。 • 例如:int *p;int a=5;cout<<*p;
内存 … 地址 1000H 1004H 1008H 3000H 4 a[0] a[1] a[2] … p q 1000 … 指针的运算 • 对指针也可以进行一些运算: • 赋值(=)、取地址(&)、取值(*) • 比较、加减运算 • 比较和加减运算 • 比较运算 • 所指向的变量在内存中的位置关系。 • 例如:p>q; p==q; p==0; q==NULL; • 加减运算 • 在某种条件下,可与整数或指针相加减 • 例如:p+1; q++; q-p 5 6 1004
内存 1000H 1004H 1011H 1019H 1000 pi1 pi2 pd1 pd2 边学边练 • 问题:分析下列程序的运行结果,指出指针加1与地址值加1的不同。 i 4 #include <iostream.h> void main() { int i,*pi1=&i,*pi2; double d,*pd1=&d,*pd2; pi2=pi1+1; pd2=pd1+1; cout<<pi2-pi1<<','<<pd2-pd1<<endl; cout<<(int)pi2-(int)pi1<<','; cout<<(int)pd2-(int)pd1<<endl; } 5 3456 d 7763 1004 1011 运行结果: 1,1 4,8 1019
a[0] a[1] a[2] a[3] a[4] 1000 1004 1008 1012 1016 构造数据类型 6.3指针与数组 • 指针与数组 • 数组名为数组的首地址,相当于指针常量。 例如:int a[5]={1,2,3,4,5}; 地址:a+1 &a[1] 值: *(a+1) a[1] a a+1 a
a[0] a[1] a[2] a[3] a[4] 1000 1004 1008 1012 1016 6.3.1用指针访问一维数组 • 数组元素可以用下标表示,也可以用指针表示。 • 一维数组的指针表示 例如:int a[5]={1,2,3,4,5}; int *p;p=a; p p+1 a • a数组的第三个元素,可以表示为 • a[2],*(a+2),*(p+2) ,p[2]
例6.5 • 问题:分析下列程序的输出结果,分析一维数组元素的指针表示。 #include <iostream.h> int a[]={1,3,5,7,9}; void main() { int *p; for(int p=a;p<a+5;p++) cout<<*p<<" "; cout<<endl; for(int i=0;i<5;i++) cout<<p[-i]<<' '; cout<<endl; }
a[0][1] a[0][3] a[0][2] a[0][0] a a[0] a[0]+0 a[0]+1 a[0]+2 a[0]+3 a[1] a[1][2] a[1][3] a[1][0] a[1][1] *(a+1)+2 *(a+1)+3 *(a+1)+0 *(a+1)+1 a[2] a[2][2] a[2][3] a[2][0] a[2][1] 6.3.1用指针访问二维数组 • int a[3][4] *a[1] ? (*a)[1] (*(a+0))[1] 2000H *(a+0) *(a[0]+0) *a[0] 2016H *(a+1) *(*(a+1)+0) **(a+1) 2032H *(a+2) *(&a[0][0]+9) *(&a[0][0]+4*i+j) *(&a[0][0]+4*2+1)
a a[0] 1 3 5 a[1] 7 9 11 例6.6 运行结果: 0x0042AD50,0x0042AD50,1 0x0042AD50,0x0042AD500 0x0042AD5C,0x0042AD5C,0x0042AD5C 0x0042AD5c,7,7 9,9,9 • 问题:分析下列程序输出结果,理解二维数组各种表示方法。 *(a+0) #include <iostream.h> int a[2][3]={1,3,5,7,9,11}; void main() { cout<<a<<','<<*a<<','<<**a<<endl; cout<<a[0]<<','<<&a[0]<<endl; cout<<a[1]<<','<<a+1<<','<<*(a+1)<<endl; cout<<&a[1]<<','<<**(a+1)<<','<<(*(a+1))[0]<<endl; cout<<a[1][1]<<','<<*(*(a+1)+1)<<','<<*(a[1]+1)<<endl; } a+1 *(a+1)
name name[0] Fortran name[1] BASIC 构造数据类型 指针数组 • 指针数组 • 如果一个数组中的元素均为指针类型的数据,则称这个数组为指针数组。 • 其定义方式为: 类型标识符 * 数组名[数组长度]; • 如: int *p[4] ; • 这种指针数组比较适合于处理字符串。 • 如: char *name[2]={“Fortran”, “BASIC”};
构造数据类型 6.3.2指针与字符串 • 字符数组与字符指针 • 字符串一般被存放在字符数组中。 • 可以使用字符指针来访问字符串。 • 如: void main() { char str[20]=“c++ language”; char *ps=“c++ language”; cout<<ps<<str; cout<<*ps<<*str; } • 注意:str和*str不同的输出结果。
构造数据类型 指向指针变量的指针 • 指向指针变量的指针 • 指针变量和普通变量一样,在内存中也占存储单元,所以指针变量也有其地址,这就是指针变量的指针。 • 定义指向指针的指针变量的方式为: 类型标识符号 **变量名; • 例如: #include <iostream.h> void main() { int *p;int a=4; int **q; p=&a; q=&p; cout<<**q<<endl; } #include <iostream.h> void main() { char *p="abc",**q; q=&p; cout<<*q<<**q<<q<<endl; }
构造数据类型 6.4.1指向函数的指针 6.4指针与函数 • 函数的指针 • 在C++中,函数的名称就代表了该函数的首地址。 • 指向函数的指针变量的定义形式为: 数据类型标识符 (*指针变量名)(形参列表 ); • 指向函数指针的调用格式:(*<指针名>)(<实参表>) • 例如: • double (*p)(double); • p=sin; • double z=(*p)(10);//double z=sin(10);
例6.10 • 问题:编程验证主函数参数argv是用来存放命令行参数的内容。 #include <iostream.h> void main(int argc,char* argv[]) { for(int i(1);i<argc;i++) cout<<*(argv+i)<<“ ”; cout<<'\n'; } 假定该程序编译后的可招待文件名为a.exe。 当执行下列命令行时: c:\>a prog1.cpp prog2.cpp prog3.cpp↙ 输出结果如下: prog1.cpp prog2.cpp prog3.cpp
构造数据类型 6.4.3返回指针值的函数 • 返回指针值的函数 • 定义方式为:类型标识符号 *函数名(参数名) • 如: int * a(int x, int y) {……} • 注意:该函数体内的return语句的形式为:return(指针); char* month_name(int n) { char* month[]= { "Illegal month","Jannary","Februray","March", "April", "May","June","July","August","September", "October","November","December"}; return(n>=1&&n<=12)?month[n]:month[0]; }
6.5C++语言的动态存储分配 • 动态存储分配要使用指针、运算符new和delete。 • new运算符 • 作用:申请并分配内存的地址赋给指针变量。 • 格式: <指针>=new<类型>;或<指针>=new<类型>(<初值>); • delete运算符 • 作用:释放先前申请到的存储块,并将其归还到堆中。 • 格式:delete <指针>; • 例如: #include<iostream.h> void main() { int *p=new int(5);//int *p,a=5;p=&a; x=*p; …… delete [ ]p; }
构造数据类型 小结 • 指针 • 指针就是某一存储单元的地址,指针变量是专门存放其他变量指针的变量,当指针变量中存放了某一变量的地址时,则称该变量指向那个变量。 • 因此,指针变量可以指向变量、数组、函数、字符串、结构体等。 • 指针还可以作为函数的参数,以传递实参的地址。