最近面试遇到了指针常量和常量指针,所以想整明白点
1、指针常量——指针类型的常量(int *const p)
本质上一个常量,指针用来说明常量的类型,表示该常量是一个指针类型的常量。在指针常量中,指针自身的值是一个常量,不可改变,始终指向同一个地址。在定义的同时必须初始化。用法如下:
int a = 30,b = 20;
int * const p = &a;
*p = 30; // p指向的地址是一定的,但其内容可以修改
2、常量指针——指向“常量”的指针(const int *p, int const *p)
常量指针本质上是一个指针,常量表示指针指向的内容,说明该指针指向一个“常量”。在常量指针中,指针指向的内容是不可改变的,指针看起来好像指向了一个常量。用法如下:
int a = 10, b = 20;
const int *p = &a;
p = &b; // 指针可以指向其他地址,但是内容不可以改变
先来看下面四组
const int* p //p可变,p指向的内容不可变
int const *p //p可变,p指向的内容不可变
int* const p //p不可变,p指向的内容可变
const int* const p //p和p指向的内容都不可变
是不是感觉到了模糊,没事,教你一句口诀:左数右指
当const出现在*左边时,指针指向的数据为常量,也就是这个地址可以改变,
当const出现在*右边时,指针本身为常量,也就是p这个地址不变,但其指向的内容可变
下面来看几个例子
int i = 0;
const int* p1 = &i;
int const* p2 = &i;
int* const p3 = &i;
const int* const p4 = &i;
*p1 = 1; // compile error根据左数右指,p1指向的数据为常量,所以无法修改
p1 = NULL; // ok根据左数右指,p1本身为变量,所以修改其保存的地址为空
*p2 = 2; // compile error同上
p2 = NULL; // ok同上
*p3 = 3; // ok根据左数右指,p3本身为常量,而其所指向内容可变,所以可以修改
p3 = NULL; // compile errorp3本身为常量,所以无法修改
*p4 = 4; // compile error根据左数右指,p4所指向的指不会改变
p4 = NULL; // compile error而且,p4本身也不会改变
再举栗子
int main()
{
int m = 10;
const int n = 20; // 必须在定义的同时初始化
const int *pt1 = &m; //根据左数右指, 指针指向的内容为常量,不可改变,但指针本身可以改变
int * const pt2 = &m; // 指针本身为常量,不可以指向其他的地方
pt1 = &n; // ok,pt1本身为变量,所以地址可以修改
pt2 = &n; // error,pt2本身为常量,所以无法修改
*pt1 = 3; // error,但其指向内容为常量
*pt2 = 4; // ok pt2所指向内容可以修改
int *pt3 = &n; // error常量地址不能初始化普通指针,常量地址只能赋值给常量指针
const int * pt4 = &n; // ok 根据左数右指,pt4为常量指针,用常量地址初始化常量指针
int * const pt5; //error, pt5为指针常量,定义时必须初始化
pt5 = &m; // error,指针本身为常量
const int * const pt6 = &m; //pt5本身和pt5所指向内容均不可改变
*pt6 = 5; // error不能改变内容
pt6 = &n; // error不能指向其他地方
const int * pt7; // ok,pt7为常量指针,
pt7 = &m; // ok,指向内容为常量,但地址可以修改
int * const pt8 = &n;//ok,pt8为指针常量,指向内容可变
*pt8 = 8;//ok,pt8内容可修改
return 0;
}
最后判断下面程序对错,并说明理由
int main()
{
char * const str = "apple";
* str = "orange";
printf("%s\n",str);
getchar();
}
错误
"apple"是字符串常量放在常量区,str指向"apple",那么str指向的是字符串常量"apple"的首地址,也就是字符a的地址,因此str指向字符a,*str就等于字符a,对*str的修改就是对字符串首字符a的修改,但"apple"是一个字符串常量,常量的值不可修改。
根据字符串赋值规则,可以修改整个字符串,方法是对指向字符串的指针str进行赋值,如下:
str = "orange";
但依旧是错误的,在该赋值语句中,系统会在常量区一块新的空间写入字符串"orange"并返回其首地址,此时str由指向字符串常量"apple"的首地址变为指向字符串常量"orange"的首地址,str指向的地址发生了变化,但str是指针常量不能被修改,所以错误。
如果想要程序编译通过,就不能将str声明为指针常量,否则str在初始化之后就无法修改。因此将const修饰符去掉,并修改字符串赋值语句,修改后程序如下:
int main()
{
char * str = "apple";
str = "orange";
printf("%s\n",str);
getchar();
}