一、指针使用三部曲:①定义指针变量②关联指针变量③解引用(赋值)
#include
int main(void)
{
int a = 0,b=8;
int *p; //第一步:定义指针变量
p = &a; //第二步:关联指针指向的地址
*p = 555; //第三步:解引用 作为左值 去获取指向内存单元所存储的右值
printf("*p = %d a = %d\n", *p,a);//*p = 555 a = 555
*p = b;
printf("*p = %d b = %d\n", *p,b);//*p = 8 b = 8
return 0;
}
注意:
① 在定义指针变量的时候如果没有关联指向地址,那么在之后就不可以用*p=&a来关联地址,但是可以直接在定义指针变量时直接关联int *p = &a。
② 因为指针不是普通变量所以在解引用时不可以直接将指针当做普通变量的左值来进行直接赋值。只能让指针通过“ * ”来解引用,作为左值比如*p = 555;
③ 指针实现的是间接访问,当指针定义之后,一旦关联了其他变量(内存单元)的左值,就相当于指针和变量的存储地址相等,牵一发而动全身,其中一个改变,两个都会改变。
④ 当指针定义之后需进行解引用时,要判断指针是否关联了其他变量(内存单元),如果未关联就是野指针,大概率会造成不可预料的错误,关于野指针我们下篇再谈。
二、指针使用中 “*”星号的作用
星号在用于指针相关功能的时候有2种用法
① 第一种是指针定义时,*结合前面的类型用于表明要定义的指针的类型
int * p 去掉指针变量名 p ,*与类型int结合 表示指针类型为 int *
② 第二种功能是指针解引用(赋值),解引用(赋值)时*p表示p所关联变量的内存单元,强调的是左值。
*p = b 表示*p指向的变量b的左值(内存单元)
*P作左值时意义和b完全等价,内存单元相同
*P作右值时 *P存储的数据内容和变量b存储的数据内容完全一样
三、指针使用中“&”&号的作用
取地址符使用时直接加在一个变量的前面,然后取地址符和变量加起来构成一个新的符号,这个符号表示这个变量的地址。
比如 :&a 意思是取变量a的左值(内存单元)
注意:在与指针相关的使用中 & 此符号只在指针定义需关联存储地址时以及作为函数传输的实参进行使用。
四、指针名作左值与右值
#include
int main(void)
{
unsigned int a[3]= {1,2,3};
unsigned char b[3]= {4,5,6};
unsigned int * p = 0;
unsigned char * c = 0;
p = a;
printf("p_val = %d p_addr = %p\r\n",*p,p);
//p_val = 1 p_addr = 0019FF24
p++;//自增 偏移
printf("p_val = %d p_addr = %p\r\n",*p,p);
//p_val = 2 p_addr = 0019FF28
c=&b[0];
printf("c_val = %d c_addr = %p\r\n",*c,c);
//c_val = 4 c_addr = 0019FF20
c++;//自增 偏移
printf("c_val = %d c_addr = %p\r\n",*c,c);
//c_val = 5 c_addr = 0019FF21
return 0;
}
①作为左值 p和&结合使用 表示关联内存地址
p和预算符(++、--)结合,指针地址的偏移计算
注意:指针偏移计算的单位偏移量与指针的类型有关 比如 int * 类型地址逐次+4 char *类型地址逐次+1,依次类推。
②作为右值 p是取指针关联变量的内存地址
五、实例
#include
int main(void)
{
int a = 1,b = 4;
int *p=&a;//初始化并指向a的左值(内存单元)
printf("①a(val) = %d *p(val) = %d b(val) = %d a(addr) = %p *p(addr) = %p b_addr = %p\n\n", a,*p,b,&a,p,&b);
//①a(val) = 1 *p(val) = 1 b(val) = 4 a(addr) = 0019FF2C *p(addr) = 0019FF2C b_addr = 0019FF28
a = 2; //修改a作为左值的右值为常量2
printf("②a(val) = %d *p(val) = %d b(val) = %d a(addr) = %p *p(addr) = %p b_addr = %p\n\n", a,*p,b,&a,p,&b);
//②a(val) = 2 *p(val) = 2 b(val) = 4 a(addr) = 0019FF2C *p(addr) = 0019FF2C b_addr = 0019FF28
*p = 3; //用*p作为左值去修改p所指向左值(内存单元)的右值为常量3
printf("③a(val) = %d *p(val) = %d b(val) = %d a(addr) = %p *p(addr) = %p b_addr = %p\n\n", a,*p,b,&a,p,&b);
//③a(val) = 3 *p(val) = 3 b(val) = 4 a(addr) = 0019FF2C *p(addr) = 0019FF2C b_addr = 0019FF28
*p = b; //用*p作为左值去修改p所指向左值(内存单元)的右值为变量b
printf("④a(val) = %d *p(val) = %d b(val) = %d a(addr) = %p *p(addr) = %p b_addr = %p\n\n", a,*p,b,&a,p,&b);
//④a(val) = 4 *p(val) = 4 b(val) = 4 a(addr) = 0019FF2C *p(addr) = 0019FF2C b_addr = 0019FF28
p = &b; //用p去重新关联变量b的左值(内存单元)
printf("⑤a(val) = %d *p(val) = %d b(val) = %d a(addr) = %p *p(addr) = %p b_addr = %p\n\n", a,*p,b,&a,p,&b);
//⑤a(val) = 4 *p(val) = 4 b(val) = 4 a(addr) = 0019FF2C *p(addr) = 0019FF28 b_addr = 0019FF28
return 0;
}