2008年(35)
分类: C/C++
2008-04-01 16:12:01
对于下面涉及指针定义和操作的语句:
int a=1;
int *pi;
pi=&a;
*pi=58;
可以看到,一个指针涉及到两个变量,指针本身pi和指向的变量a。修改这两个变量的对应操作为“pi=&a;”和“*pi=58;”。
1.指向常量的指针(常量指针)
在指针定义语句的类型前加const,表示指向的对象是常量。例如:
const int a=78;
const int b=28;
int c=18;
const int*pi=&a; //指针类型前力口const
*pi=58; //error:不能修改指针指向的常量
pi=&b; //ok:指针值可以修改
*pi=68; //error:同上
pi=&c;
*pi=88; //error:同上
c=98; //ok
a是常量,将a的地址赋给指向常量的指针pi, 使a的常量性有了保证。如果企图修改a,则会引起“不能修改常量对象”(Cannot modify a const object)的编译错误。
可以将另一个常量地址赋给指针“pi=&b;” (指针值可以修改),这时,仍不能进行“*p =68;”的赋值操作,从而保护了被指向的常量不被修改。 见图8-4,图中阴影部分表示不能
图8-4 指向常量的指针
被修改。可以将一个变量地址赋给指针“pi=&c;”, 这时,由于不能进行“*pi=88;”的赋值操作,从而保护了被指向的变量在指针操作中不被修改。定义指向常量的指针只限制指针的间接访问操作,而不能规定指针指向的值本身的操作规定性。例如,变量c可以修改,这在 函数传递中经常被使用。
例如,下面的程序将两个一样大小的数组传递给一个函数,让其完成复制字符串的工作,为了防止作为源数据的数组遭到破坏,声明该形参为常量字符串:
//**********************
//** ch8_10.cpp **
//**********************
#include
void mystrcpy(char* dest, const char* source)
{
while(*dest++ = *source++);
}
void main()
{
char a[20]="How are you!";
char b[20];
mystrcpy(b,a);
cout < }
运行结果为:
How are you!
变量字符串a传递给函数mystrcpy()中的source, 使之成为常量,不允许进行任何修改、但在主函数中, a却是一个普通数组,没有任何约束,可以被修改。
由于数组a不能直接赋值给b, 所以通过一个函数实现将数组a的内容复制给数组b。
函数mystrcpy()中的语句是一个空循环,条件表达式是一个赋值语句。随着一个赋值动作,便将一个a数组中的字符赋给了b数组中对应的元素,同时两个数组参数都进行增量操作以指向下一个元素。只要所赋的字符值不是'\0',(条件表达式取假值),则循环就一直进行下去。 ,
常量指针定义"const int *pi=&a;”告诉编译,*pi是常量,不能将,pi作为左值进行操作。
2.指针常量
在指针定义语句的指针名前加const,表示指针本身是常量。例如:
char *constpc="asdf"; //指针名前加const定义指针常量
pc="dfgh"; //error:指针常量不能改变其指针值
*pc='b'; //ok:pc内容为,'bsdf',
*(pc+1)='c'; //ok:pc内容为'bcdf',
*pc++='y'; //error:指针常量不能改变其指针值
const int b=28;
int* const pi=&b; //error:不能将const int*转换成int*
pc是指针常量,在定义指针常量时必须初始化,就像常量初始化一样。这里初始化的 值是字符串常量的地址,见图8_5
图8_5 指向变量的指针常量图
由于pc是指针常量,所以不能修改该指针值。“pc="dfgh";”将引起一个“不能修改常量对象”(Cannot modify a const object)的编译错误。
pc所指向的地址中存放的值并不受指针常量的约束,即*pc不是常量,所以“*pc='b';”和“*(pc+1)='c';”的赋值操作是允许的。但“*pc++=y;”是不允许的,因为该语句修改*pc的同时也修改了指针值。
由于此处*pi是不受约束的,所以,将一个常量的地址赋给该指针“int* const pi=&b;”是非法的,它将导致一个不能将const int *转换成int *的编译错误,因为那样将使修改常量(如:“* pi=38;”)合法化。
指针常量定义"int *const pc=&b;”告诉编译,pc是常量,不能作为左值进行操作,但是允许修改间接访问值,即*pc可以修改。
3.指向常量的指针常量(常量指针常量)
可以定义一个指向常量的指针常量,它必须在定义时进行初始化。例如:
const int c=7;
int ai;
const in * const cpc=&ci; //指向常量的指针常量
const int * const cpi=&ai; //ok
cpi=&ci; //error:指针值不能修改
*cpi=39; //error:不能修改所指向的对象
ai=39; //ok
cpc和cpi都是指向常量的指针常量,它们既不允许修改指针值,也不允许修改*cpc的值,见图8-6。
图8—6 指向常量的指针常量
如果初始化的值是变量地址(如&ai), 那么不能通过该指针来修改该变量的值。也即“*cpi=39;”是错误的,将引起“不能修改常量对象”(Cannot modify a const object)的编译错误。但“ai=39;”是合法的。
常量指针常量定义“coastint * coastcpc=&b;”告诉编译,cpc和* cpc都是常量,它们都不能作为左值进行操作。
补充:
引用和const
引用有着针指的优点,但是它的身份是确定的,不像指针有双重身份,所以用const修饰没什么问题。
const int &p=a;
它的意思实际上和这样写差不多
int const * const p=&a;
本身一次赋值,所指对象也不能改。这就是喜欢考的那个所谓,一个指向一个常量对象的常量指针。
试一下这么写
int const & const p=&a;
多此一举,在VC上会给出个警告,因为在语义上是重复的。