指针的本质是地址,指针即地址,地址即指针。
指针的值是某个变量的地址。
通常当指针等于某个变量的地址时,我们说该指针指向了这个变量。
例如有定义:
int a ;
int *pa ;
a = 10 ;
pa = &a ; 把变量a的地址赋给pa,即pa指向a。
另外,除了0,我们不能将其他任何数值赋值给指针变量。
就是说:pa=100; 是错误的。
但: pa = 0 ; 是对的,表示pa是一个空指针(不指向任何变量)。
今天主要说一说指针的运算。
1 指针的两个基本运算:取地址和间接访问
(1)取地址运算符:&
取地址的运算符&可以取出任何变量的地址。
我们说过当一个变量定义时,就有了变量名和变量地址,赋值以后还有变量值。
定义变量就好像是买房,如:
int a;
int *pa;
定义了两个变量,一个是int型变量a,一个是指针变量pa。
上述两个变量定义相当于买了两间房:一间房是整数类型(int类型)的,房名叫a,可以住一个int类型的数据(即整数),a的房号由系统分配;另一间房是指针类型(int *类型)的,房名叫pa,pa这间房不能住人(数据),只能住另外一间房的房号(地址)。
而且,由于pa的类型是int *(整型指针),所以只能住int型变量的地址。
那么a自己的房号(地址)是&a,pa自己的房号(地址)是&pa。
变量pa的地址是&pa,这个地址由系统分配,我们不知道是多少,而pa的值只能是一个int变量的地址,即&整型变量,或者0(空指针)。
程序1:
程序1运行结果:
a的地址是6487580,p1的值就是a的地址6487580。
p1自己的地址是6487568。
(2)间接访问运算符:*
*是间接访问运算符,访问指针所指向的变量,或者说*是取出地址里面的内容。
如果p1是指针变量,则p1的值是另外一个变量的地址,
那么*p1就是p1所指向的那个变量。
如果说&是取房号,那么*就是取出这个房号里面住的人。
假设有如下定义和语句:
int a=3;
int *p1;
p1=&a;
则*p就是a里面的内容,即3。
程序2:
最后一个输出是输出*p1,那么这里输出的就是3( &a这个地址里住的人就是3)。
程序2运行结果:
最后一行输出3就是*p1的结果,也就是房号(&a)里面的内容3。
当p1=&a后,我们说p1指向a。图示如下:
区分p1 、*p1 和&p1三者的区别
p1:是指针变量,其内容是地址。
*p1:是指针变量p1的目标变量a。
&p1:是指针变量p1本身的地址(p1的房号)。
2 赋值运算
相同类型的指针变量可以相互赋值。
比如有定义:
int *p1, *p2;
float *p3;
则p1=p2和p2=p1都是对的。
但p1=p3、p2=p3、p3=p1、p3=p2都不对。
如果程序里有如下语句:
int a = 3 ;
int *p1, *p2;
p1 = &a;
p2 = p1;
运行如图所示:
p1 = &a是把a的地址赋给 p1,即p1指向 a。
p2 = p1是把p1赋值给p2,则p2也指向a。
程序3:
程序3运行结果:
输出结果解释:
输出结果的第1-2行:
a的值是3,a的地址是6487564。
即:房号为6487564的房间中住的人是整数3。
输出结果的第3行:
输出指针变量p1的值,这个值是6487564,即a的地址。
可见指针变量是土豪,它里面不住人,住的是变量a的房号。
也可以说指针变量p1指向a。
输出结果的第4行:
输出*p1的值即3。
*p1是取出p1存放的地址(6487564)中住的人,即整数3。
输出结果的第5行:
输出指针变量p2的值。
p2的值也是6487564(因为执行了p2=p1这个操作,所以p2和p1的指向相同),即a的房号。
输出结果的第6行:
输出*p2的值即3。
*p2同样是取出p2存放的地址(6487564)中住的人,即整数3。
以上为了帮助理解,用房号比喻地址,地址就是房号。
3 总结
本节课介绍了如下内容:
- 指针的两个基本运算:取地址运算&和间接访问运算*。
- 相同类型的指针变量可以相互赋值,此时两个指针变量的指向一样。
- 用3个程序帮助理解指针运算的结果。
今天主要讲指针的运算,指针还涉及很多知识,如指针和数组的关系、结构指针、数组指针等等。
学指针不能快,必须要在已经理解并掌握了指针的基本概念和基本运算的基础上再作进一步学习,否则很容易陷入“指针很难”的怪圈而失去信心。