数据在内存中的存储和读取
1 变量对应一个内存单元,变量类型决定对应内存单元的长度
2 内存区的每个字节都有一个编号,称为地址,为8位的16进制数(从首地址开始后4个字节)
3 一个变量的地址,称为该变量的指针
4 如果有一个变量是专门用来存放另一个变量地址(即指针)的,则它称为指针变量
内存单元的访问方式
1直接存取(直接访问)方式:通过变量名对内存单元进行存取操作
int i;
i=3;
2 间接存取(间接访问)方式:通过指针变量中保存的地址,找到对应的存储单元,并对该单元进行操作的方式
int i,*i_pointer; 指针变量i_pointer中保存的值为地址值
i_pointer=&i; 取i的地址,将值赋给i_pointer
*i_pointer=3; 取指向地址的值,取该值指向其作为地址的内容,将3赋给它
变量与指针
指针变量是一种特殊变量,用来指向另一个变量
定义: int *i_pointer;
int 代表该指针指向整型变量i;*表示指针运算符,*i_pointer表示i_pointer所指向的变量
i_pointer 是一个指针变量,可以赋予一个地址值:i_pointer=&i;
&表示获得变量的地址,取地址运算符
i=3等价于*i_pointer=3
在定义指针变量时必须指定基类型(指向数据的类型)
32位平台中,每一个指针变量分配4个字节的存储单元,用来存放变量地址(如1004)
初始化: int *p=&a; 变量p的值初始化为a的地址
在使用指针变量之前,必须对指针变量赋初值,否则得到的是随机数
指针变量“指向”运算两忌
1 指针变量未赋值,即指针指向未知地址
.int *p1,*p2;
*p1=10;*p2=100; 指针变量p1指向地址的值为10,但是指向地址未知
2 抛开内存分配机制直接指定地址
.int a,b;
.int *p1,p2;
.p1=1000;p2=1004 若地址为1000的位置上的变量是内存中很重要的,则可能打乱计算机的运行机制
关于“&”和“*”运算符
1 优先级:较高,等同于++,--,!,-,+等其他一元运算符
2 结合性:从右到左
.pointer_1=&a; 先取地址,再赋值
.pointer_2=&*pointer_1; 先取1指向地址的值,再取地址,最后赋值,相当于将1的值赋给2
.int b=*&a; 先取a的地址,再取该地址指向地址的值,即a,再赋值给b,相当于将a的值赋给b
(很重要) ++,--,*优先级相同,右结合性
.int a=3,*p;
.p=&a;
(*p)++; 相当于a++
结果:a=4,整个表达式的值仍为3,因为先得表达式的值,再加加
若改成*p++; 相当于*(p++)
因为p是指向整型的指针变量,因此++后指向下一个整型,每次++加4(一个整型4个字节)
若a的地址为2000H,则p++后p的值未改变,仍为2000H,就开始执行下一步,*p值为3,即表达式为3;
p++执行完*后再++,指向下一个int单元,则p=2004H
若改成++*p: 相当于++(*p)
*p=3,++i先+1,再输出i,因此得到a=*p=4,整个表达式的值为4
若改成*++p: 相当于*(++p)
++p得到p=2004H,再取*p,即地址2004H中存放的值
用指针变量将两个数按先大后小的顺序输出
程序:
int main()
{
int a,b;
int *p1,*p2;
cin>>a>>b;
p1=&a;p2=&b;
if(a<b)
{
p1=&b;
p2=&a; 未改变a,b的值,只改变指向地址的指针,不需要引入多余参数
}
cout<<*p1<<'\t'<<*p2<<endl;
return 0;
}
另一种实现方式:
void swap(int *p1,int *p2)
{
int t;
t=*p1;
*p1=*p2;
*p2=t; 函数调用交换了a,b的值,而p1,p2(即地址)没有改变
}
void main()
{
int *p1,*p2,a,b;
cin>>a>>b;
p1=&a;
p2=&b;
if (a<b)
swap(p1,p2); 相当于初始化 ,将地址赋给指针
cout<<*p1<<'\t'<<*p2<<endl;
}
因此,指针变量做函数参数,在被调函数执行时,应该使指针变量所指向的参数值发生变化,这样,函数在调用结束后,变化值才能保留回主调函数(函数调用不能改变实参指针变量的值,但可以改变实参指针变量所指向变量的值)
指针作为函数参数
1 函数的参数可以为指针类型,作用是将一个变量的地址传送到另一个函数中去
2 指针变量作为函数参数与变量本身做函数参数不同,变量做函数参数传递的是具体值,而指针做函数参数传递的是内存的地址
通过函数调用得到n个要改变的值(步骤):
1 在主调函数中设n个变量,用n个指针变量指向他们
2 编写被调用程序,形参为n个指针变量,这些形参指针变量应当与主调函数中的n个指针变量具有相同的基类型
3 在主调函数中将n个指针变量作实参,将它们的值(地址值)传给所调用函数的n个形参指针变量,这样,形参指针变量也指向这n个变量
4 通过形参指针变量的指向,改变这n个变量的值,在主调函数中就可以使用这些改变了值得变量
数组和指针
指针变量可以指向数组元素,数组元素的指针就是数组元素的地址
例:int *p;
.p=&a[0];
数组名代表数组的起始地址
int a[10];
int *p;
p=a; 将数组名赋给指针p
等价于:p=&a[0];
定义指针变量时赋初值:
.int *p=&a[0];
.int *p=a; 将首地址赋给指针变量
通过指针引用数组元素:
*p=100; 表示数组的首地址中存放100,即a[0]=100;
*(p+1) 1不表示一个字节,而是一个单元,如果为整型则为4个字节,取a[1]的值
数组名等同于指向数组的指针
p+i和a+i都是a[i]的地址,它们都指向a数组的第i个元素
*(p+i)和*(a+i)是所指向的数组元素,即a[i]
【】是变址运算符 优先级很高,结合性自左向右
对a[i]的求解过程:先按a+i*d计算数组元素的地址(d为数组元素类型占用字节数),然后找出此地址所指向的单元中的值
指向数组元素的指针变量p也可以带下标,p[i]与*(p+i)等价
即:p[i]=a[i]