今天我们来看看指针的问题:
指针:用来保存地址的“变量”叫做指针。你可以理解为指针就是地址。
如何定义一个指针:
int a = 1;
int *p = &a;
p现在是a的指针,对p进行*(解引用)就是a的值1。
指针常量:
*(int *)10 = 100;
意思就是我们将10强转成int *类型的整形地址,再对其就行*(解引用)就拿到一块空间,然后再对其赋值。
常量指针:
int *p = &10;
就是指针指向一个常量,一般用不上。
二级指针:
存放地址的变量叫做指针,那么二级指针就是存放一级指针地址的变量。
在如上的A指向B、B指向C的指向关系中,如果A、B、C都是变量,即C是普通变量,B是一级指针变量,其中存放着C的地址,A是二级指针变量,其中存放着B的地址,则这3个变量分别在内存中占据各自的存储单元,它们之间的相互关系上图图所示,相互之间的前后位置关系并不重要.此时,B是一级指针变量,B的值(即C的地址)是一级指针数据;A是二级指针变量,A的值(即B的地址)是二级指针数据。
分析一下下面几种情况能不能作为可修改的左值:
int a=10;
int *cp=&a;
*cp=20 //可以作为左值,当cp指向a时,*cp放到等号左边代表a这块空间,当*cp放到等号右边代表a这块空间的值。
&a=20 // 错误,&a不可以作为左值,因为他不能表示一块特定的空间,&a得到的结果是a的地址,但并不代表a这块空间,要想使用这块空间,必须进行*引用,*&a=20正确。&a可以作为右值,代表是a的地址这个数值。
*cp+1 //不可以作为左值,因为*优先级高于+,所以*cp先结合,再加1相当于10+1,不代表一块空间。
*(cp+1) //可以作为左值,cp+1先结合,指向a的下一块空间,再对这块空间进行*引用,放在等号左边就代表这块空间
++cp //不可以作为左值,因为++cp只是将cp里面的内容加一,并没有进行*引用
cp++ //不可以作为左值
*cp++ //可以作为左值,先对cp里面的地址进行*引用。再让cp=cp+1(也就是让cp指向a的下一块空间,因为++优先级高于*)
++*cp //不可以作为左值,*cp代表cp所指向的内容,再让其加一,相当于10+1
注意:C中++cp和--cp都不能做左值,C++中++cp可以作为左值。
const 修饰一级指针,修饰二级指针:(const修饰的变量,还是一个变量,只不过只是可读的 )
int const a=10;
int b=30;
1、a=20; //错误,const修饰a,所以不能改变a的值
2、int const *p; //const修饰的是*p,所以不能改变*p
p=&a; //正确
*p=20; //错误 不能通过*p改变a的值
3、const int *p; //const修饰的是*p
p=&a; //正确
*p=20; //错误
4、int *const p=&a; //const修饰的是p
p=&b; //错误 不能改变p
*p=20; //正确
5、int const * const p; //const修饰*p,也修饰p,所以*p,p都不能改变
p=&b; //错误
*p=20; //错误
注意:const修饰变量的原则是离谁近修饰谁。const int *p与int const *p完全一样。
指针数组与数组指针:
还有指针的运算:
指针相减得到的结果是两个指针之间元素的个数,不是字节数。