指针与const限定符
我们知道,程序通过const限定符明确说明哪些数据是不可以修改的,指针作为一种变量,它也可以与const限定符结合起来,限定对指针变量和指针所指对象的修改。
(1)指向非常量的非常量指针
如果声明指针时不使用const限定符,就可以定义指向非常量的非常量指针
例如:
int i,j;
int *p;
i = 10;
j = 20;
p = &i;
*p += 5; // 可以通过p修改它所指向的变量i的值
p = &j; // 可以修改p的指向
j += 10; // 可以通过p修改它所指向的变量j的值
通过上例,我们看到:
没有使用const可以任意修改变量 ,这给程序设计带来方便,但更可能带来安全隐患,需要将程序操作数据的权限限定在恰当的范围内,const可以支持这种限定。
(2)使用常量数据的非常量指针
可以使用const来限定指针指向的数据。例如:
int i,j;
const int *p; //p是一个指向常整数的指针,不允许通过*p来修改p所指向的数据
p = &j; //允许
p = &i; //允许
i = 10;//允许
*p = 5; //不允许
上例中声明p是一个指向常整数的指针变量,因此p本身是允许修改的,但p指向的整数不能通过p修改,即不能通过*p
来修改该整数,这并不意味着该整数不能被修改。实际上可以通过其他途径来修改。当然,也可以将一个用const修饰的int类型的变量的地址赋给p.例如:
const int val = 10;
p = &val;
*p = 20; //不允许
val = 20; //不允许
此时,不论通过p还是直接通过val,都不能修改val的值。
注意: const对象的地址只能赋值给指向const对象的指针,但是指向const对象的指针也可以指向非const对象。
在函数调用传递参数时,如果要传递的数据较多,为了提高时间和空间效率,可以考虑传递地址。但是若不希望被调函数通过形参指针修改实参的值,就可以通过合理使用const限定符,既保证实参的安全,有避免赋值大量的数据而带来的时空开销。
/*使用const防止无意修改实参的值*/
#include <iostream>
using namespace std;
void mystrcpy(char *Dest,char *Src){
while(*Dest++ = *Src++);
}
int main(void){
char a[20] = "How are you!";
char b[20];
mystrcpy(b,a);
cout<<b<<endl;
return 0;
}
(3)指向非常量数据的常量指针
如果想声明一个不可修改的指针变量,保证该指针总是指向固定的内存单元,则需要声明指针为常量指针。例如:
int v1,v2;
int *const p = &v1;
*p = 5; //允许
p = &v2;
上例中,声明p为一个指向整型变量的常量指针,因此在声明p的同时需要对p进行初始化。被初始化后,p的值不允许再被修改,即p只能指向v1,但可以通过p修改p所指向的变量的值。此外,p是指向整形变量的,也不能将const修饰的整形变量的地址赋给p。例如;
const int val = 10;
int *const p = &val; //不允许
(4)指向常量数据的常量指针
可以使用const同时限定指针和指针指向的数据,此时,指针和指针指向的内容都为常量。例如:
const int val = 10;
const int *const p = &val;
*p = 5; //不允许
上例中,val是一个常整型变量,初始化后不可再修改。p是一个指向常整数的常量指针,p在初始化指向val后也不能修改,同时也不能通过p去修改它所指向的变量val的值。