第17节 指针的定义与使用
1.指针的定义
1、指针的概念
►在程序设计过程中,无论是存入数据还是取出数据都需要与内存单元打交道,计算机通过地址编码来表
示内存单元。指针类型就是为 了处理计算机的地址数据的。
►指针除了能够提高程序的效率,更重要的作用是能使一个函数访问另一个函数的局部变量,因此指针是
两个函数进行数据交换必不可少的工具。
►1. 地址和指针的概念
►程序中的数据对象总是存放在内存中,在生命期内这些对象占据一定的存储空间,有确定的存储位置。
►实际上,每个内存单元都有一个地址,即以字节为单位连续编码。编译器将程序中的对象名转换成机器
指令能识别的地址,通过地址来存取对象值。
int i;
double f;
![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/968bbd2058bd43c59ce390411c806f7d.png)
►按对象名称存取对象的方式称为对象直接访问。
►如:i=100; f=3.14
►通过对象地址存取对象的方式称为指针间接访问。
2、指针的定义
►C++将专门用来存放对象地址的变量称为指针变量,定义形式如下:
指针类型 *指针变量名, ......
►例如:
int *p, i;
p = &i ;
![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/0c8ff594143f42ca92fde8c6d7a1d875.png)
表17-1 取地址运算符
*************************************************
运算符 | 功能 | 目 | 结合性 | 用法
*************************************************
& | 取地址 | 单目 | 自右向左 | &expr
*************************************************
►假定指针变量p的值是4000,下面三种写法:
①char *p; ②int *p; ③double *p;
![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/53f9ffc62f674aea8f550e234f21262b.png)
►2. 指针的间接访问
►通过间接引用运算(*)可以访问指针所指向的对象或内存单元
表17-2 间接引用运算符
*************************************************
运算符 | 功能 | 目 | 结合性 | 用法
*************************************************
* | 间接引用 | 单目 | 自右向左 | *expr
*************************************************
int a, *p=&a;
a=100;
*p=100;
*p=*p+1;
![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/c7f2157982064fb6adcdf9de1a1fa0cb.png)
【例17.1】已知:
int a, b, *p1=&a, *p2;
则①&*p1的含义是什么?②*&a的含义是什么?
&*p1 <---> p1 <---> &a
*&a <---> a <---> *p
【例17.2】指针举例。
1 int main()
2 {
3 int i=100, j=200;
4 int *p1, *p2;
5 p1=&i, p2=&j;
6 *p1 = *p1 + 1;
7 p1=p2;
8 *p1 = *p1 + 1;
9 return 0;
10 }
►3. 指针的初始化
►可以在定义指针变量时对其初始化,一般形式为:
指针类型 *指针变量名=地址初值,......
int a;
int *p=&a;
int b, *p1=&b;
►由于指针数据的特殊性,其初始化和赋值运算是有约束条件的,只能使用以下四种值:
►(1)0值常量表达式,例如:
int a, z=0;
int *p1=a;
p1=z;
p1=4000;
p1=null;
p1=0;
►(2)相同指向类型的对象的地址。例如:
int a, *p1;
double f, *p3; p1=&a;
p3=&f;
p1=&f;
►(3)相同指向类型的另一个有效指针。例如:
int x, *px=&x;
int *py=px;
►(4)对象存储空间后面下一个有效地址,如数组下一个元素的地址。
int a[10], *px=&a[2];
int *py=&a[++i];
2.指针的有效性和运算
3、指针的有效性
►指针指向一个有确定存储空间的对象(称为已知对象),则该指针是有效的。
►若一个指针不指向程序中任何已知对象,称其指向未知对象。未知对象的指针是无效的,无效的指针使用
间接引用运算几乎总会导致崩溃性的异常错误。
►(1)如果指针的值为0,称为0值指针,又称空指针(null pointer),空指针是无效的。
int *p=0;
*p=2;
►(2)如果指针未经初始化,或者没有赋值,或者指针运算后指向未知对象,那么该指针是无效的。
int *p;
*p=100;
►(3)一个指针曾经指向一个已知对象,在对象的内存空间释放后,虽然该指针仍是原来的内存地址,但指针
所指已是未知对象,称为 “迷途指针”(dangling pointer)。
char *p=NULL;
void fun()
{
char c;
p = &c;
}
void caller()
{
fun();
*p=2;
}
4、指针的运算
►指针的运算都是作用在连续存储空间上才有意义。
►(1)指针加减整数运算
int x[10], n=3 , *p=&x[5];
p+1
p+n
p-1
p-n
►(2)指针变量自增自减运算
►设p是一个指针变量,其自增自减运算包括p++、++p、p--、--p 形式。
int x[10], *p=&x[5];
p++
++p
p--
--p
►(3)两个指针相减运算
►设p1、p2是相同类型的两个指针(常量或变量),则p2-p1的结果为两个指针之间对象的个数,如
果p2的地址值大于p1结果为正,否则为负。
int x[5], *p1=&x[0],*p2=&x[4];
int n;
n=p2-p1;
►(4)指针的关系运算
►设p1、p2是同一个指向类型的两个指针(常量或变量),则p2和p1可以进行关系运算,用于比较
这两个地址的位置关系。
int x[5], *p1=&x[0],*p2=&x[4];
p2>p1
►指针的const限定
►(1)一个指针变量可以指向只读型对象,称为指向const对象的指针,定义形式为:
const 指向类型 *指针变量,......;
►即在指针变量定义前加const限定符,其含义是不允许通过指针来改变所指向的const对象的值。
const int a=10, b=20;
const int *p; p=&a;
p=&b;
*p = 42;
►把一个const对象的地址赋给一个非const对象的指针变量是错误的,例如:
const double pi = 3.14;
double *ptr = π
const double *cptr=π
►允许把非const对象的地址赋给指向const对象的指针;不能使用指向const对象的指针修改指向
对象,然而如果该指针指向的是一个非const对象,可用其他方法修改其所指的对象。例如:
const double pi = 3.14;
const double *cptrf = π
double f = 3.14;
cptrf = &f;
f=1.618;
*cptrf = 10.1;
►实际编程中,指向const的指针常用作函数的形参,以此确保传递给函数的实参对象在函数中不
被修改。
void fun( const int *p)
{
……
}
int main()
{
int a; fun(&a);
}
►(2)const指针
►一个指针变量可以是只读的,称为const指针,定义形式为:
指向类型 * const 指针变量,......;
int a=10, b=20;
int *const pc = &a;
pc = &b;
pc = pc;
pc++;
*pc=100;
►pc是指向int型对象的const指针。
►不能使pc再被赋值指向其他对象。任何企图给const指针赋值的操作都会导致编译错误。
►但可通过pc间接引用修改该对象的值。
►(3)指向const对象的const指针
►可以定义指向const对象的const指针,形式为:
const 指向类型 * const 指针变量,......;
const double pi = 3.14159;
const double * const cpc = π