1.6 指针
C++编译系统一般为整形变量和单精度浮点型变量分配4个字节,为字符型变量分配一个字节。
&是取地址运算符,&i是变量i的地址。通过地址的访问称为间接访问。一个变量的地址称为改变量的指针。若整形变量i的地址是2000,则2000就是整形变量i的指针。如果有一个变量是专门用来存放一个变量地址的,则称它为指针变量。
1.6.1 变量与指针
变量的指针就是变量的地址,用来存放变量地址的变量就是指针变量。i_pointer是一个指针变量,*i_pointer表示i_pointer所指向的变量。详情见图1.3。
图 1.3 指针变量与变量的关系
可以发现,*i_pointer是一个变量,它就是i_pointer所指向的变量i。即i=3等价于*i_pointer=3。
定义指针变量:
基类型 *指针变量名
int *pointer_1;//定义指针变量pointer_1,且该变量是指向整形数据的指针变量
int就是指针变量的基类型。
使指针变量指向一个变量:
int *pointer_1;
pointer_1=&i;//把i的地址存放到指针变量pointer_1中
&:取地址运算符
*:指针运算符
&*pointer_1:&和*的优先级相同,按自右向左的方向结合,因此等价于&(*pointer_1),由于*pointer_1等价于i,因此&(*pointer_1)等价于&a。
*&i:先得到i的地址,在进行*运算,即&i指向的变量,等价于i。
1.6.2 指针作为函数参数
声明:
函数类型 函数名(指针类型 *指针名1,指针类型 *指针名2);
调用:
函数名(指针名1,指针名2);
函数名(*指针名1,*指针名2);//错误,*指针名1是变量不是地址
实参变量焦耳形参变量之间的数据传递是单向的“值传递”方式,调用函数时不会改变实参指针变量的值,但可以改变实参指针所指向的变量的值。
例 1.6.1输入3个数,按照由大到小顺序输出,使用指针。
#include<iostream>
using namespace std;
int main()
{
void exchange(int *,int *,int *);//对exchange函数作声明
int a,b,c,*p1,*p2,*p3;
cin>>a>>b>>c;
p1=&a;p2=&b;p3=&c;//使3个指针指向3个整形变量
exchange(p1,p2,p3);//交换p1,p2,p3指向的3个整形变量的值
cout<<a<<” “<<b<<” “<<c<<endl;
}
void exchange(int *q1,int *q2,int *q3)
{
void swap(int *,int *);//函数的嵌套调用,交换2个指针所指向的变量的位置
if (*q1<*q2) swap(q1,q2);
if (*q1<*q3) swap(q1,q3);
if (*q2<*q3) swap(q2,q3);
}
void swap(int *pt1,int *pt2)//将pt1和pt2所指向的变量的值互换
{
int temp;
temp=*pt1;
*pt1=*pt2;
*pt2=temp;
}
1.6.3 数组与指针
指向数组元素的指针 | int a[10]; int *p; p=&a[0];//将a[0]的地址赋给指针变量p 数组名代表数组中的一个元素的地址,因此: p=&a[0]; p=a; 是等价的 | ① p+i和a+i就是a[i]的地址。 ② a代表数组元素的首地址。 ③ *(p+i)和*(a+i)是p+i和a+i所指向的数组元素,即a[i]。 |
指向多维数组的指针 | int a[3][4]; a代表首行的起始地址,即&a[0]。 a+1代表a[1]行的起始地址,即&a[1]。 a[0]代表一维数组a[0]中第0列元素的地址,即a[0][0]。 不能写成p=a,因为a指向的是a[0](即a指向一个一维数组),p指向的是整形数据。 | 第0行第1列元素的地址为:&a[0][1],或者a[0]+1。 第0行第1列元素的值为:*(a[0]+1)。 第i行第j列元素的值为:*(a[i]+j)。 注意: 当定义:int (*p)[4]时,表示p是指向一个包含4个整形元素的一维数组,此时p+1指向的不再是a[0][1],二是a[1]。p的增值以一维数组的长度为单位。且此时可使用p=a。 此时*(*(p+i)+j)是a[i][j]的值。 |
下标法 | 指针法 |
|
|
p++:使p指向下一个元素,即a[1]。
*p++:由于++和*的优先级相同,故自右向左结合,等价于*(p++),先得到*p,然后p的值再加一。
*(++p):先使p加一,再取*p。
1.6.4 字符串与指针
C++可以用3种方法访问一个字符串:字符数组,字符串变量和字符指针。
用字符指针指向一个字符串:
char *str;
str=”I love China!”;//把字符串第一个元素的地址赋给str
1.6.5 指针与函数
一、用函数指针变量调用函数(函数的指针)
指针变量可以指向一个函数,函数的入口地址就称为函数的指针。函数名代表函数的入口地址。
格式:
函数类型 (*指针变量名)(函数形参表)
int (*p)(int,int);//定义指向某一函数的指针变量
p=max;//使p指向max
int max(int,int);//max函数声明
注意括号的用法:
int *p(int,int);//声明一个函数,函数的返回值是指向整形变量的指针(返回指针值的函数)
1.6.6 指针数组
指针数组 | 类型名 *数组名[数组长度] int *p[4]; | 一个数组的元素均为指针类型的数据,该数组称为指针数组。即指针数组每一个元素的值都是地址。 |
指向一维数组的指针变量 | 类型名 (*数组名)[数组长度] int (*p)[4]; | p是指向一个包含4个整形元素的一维数组的指针变量。 |
1.7 自定义数据类型
1.7.1 结构体类型
C++允许用户自己定义这样一种数据类型,如下所示,称为结构体。
声明 | 定义 |
struct 结构体类型名 {成员列表}; Eg: struct Student //声明结构体类型Student { int num; char name[20]; char sex; int age; float score; char addr[20]; }; | ① 先声明结构体类型再定义变量名,如: Student stud1,stud2; ② 在声明结构体类型的时候定义变量: struct Student //声明结构体类型Student { …… } stud1,stud2;
|
初始化:
Studentstud1={10002,”Wang li”,’F’,20,98,”Beijing”};
引用结构体变量中成员的一般方法为:
结构体变量名.成员名(“.”是成员运算符)
Eg: stud1.num=10002;//对结构体成员num进行赋值
一、结构体数组
数组中的每个元素都是结构体类型的数据,可以处理多结构体情况。
声明:
Student stud[10];//定义stud为Student类型的数组
stud[10]={{…},{…},…{…}};//初始化
二、指向结构体变量的指针
可以设置一个指针变量,用来指向一个结构体变量,此时指针变量的值是结构体变量的起始地址。指针变量也可以用来指向结构体数组中的元素。
通过指向结构体变量的指针引用结构体变量中的成员:(*p).成员名
Student stu;//定义Student类型的变量stu
Student *p;//定义p为指向Student类型数据的指针变量
p=&stu;//使指针指向stu,把stu的地址赋给p
cout<<(*p).num<<endl;//输出p指向的结构体变量中的成员num
三、用结构体变量和指向结构体变量的指针可以构成单项链表,具体见数据结构部分。
四、C++结构体和类的区别
主要是访问权限的区别:C++结构体内部成员变量和成员函数默认的访问级别是public,而类的内部成员变量和成员函数默认的访问级别是private;C++结构体的默认继承是public,而类的默认继承是private。
1.7.2 动态分配和撤销内存的运算符new和delete
C中是利用库函数malloc和free来分配和撤销内存空间的,C++提供了较为简单的运算符new和delete来替代malloc和free。具体地,C++内存管理会在后面讲到。
new运算符 | delete运算符 |
格式: new 类型[初值] | 格式: delete [ ] 指针变量 |
new int(100);//开辟一个存放证书的空间,并指定该整数的初值为100,返回一个指向该存储单元的地址 new char[10];//开辟一个存放字符数组的空间,返回首元素地址 | char *p=new char[10];//返回的地址赋值给指针变量p delete [] p;//[]表示是对数组空间的操作 int *p=new int(100); delete p; |
new分配数组空间时,不能指定初值。若内存不足导致无法正常分配空间则new会返回一个空指针NULL。 |
|
1.7.3 枚举类型
如果一个变量有几种可能的值,则可以定义为枚举类型。
格式:
enum 枚举类型名{枚举常量列表};