04一篇彻底理解 指针常量和常量指针 指向常量的常指针

1、在汉语中,定语一般都放在中心词的前面,像C语言和C++语言这种技术性语言,更是如此。
所以定语重要还是中心词重要,肯定是中心词重要。
如:美丽的女孩 美丽的是定语 女孩是中心词
女孩肯定是重要,是本质。

2、同理:我们先不讲技术,先从字面意思来理解:
指针常量 常量指针
函数指针 指针函数

指针常量:指针是定语,常量是中心词,所以指针常量本质是一个常量。
常量指针:常量是定语,指针是中心词,所以常量指针本质是一个指针。
函数指针:本质上是一个指针。那就是指向函数的指针。
指针函数:
数组指针:本质上是一个指针,只不过是指向数组的指针。
指针数组:本质上是一个数组,只不过数组元素都是指针。

3、本文正文:

1、指针常量——指针类型的常量(int * const p)

巧记:const的作用就是将被修饰者限定为常量,所以const修饰谁,谁就是常量。

指针常量(指针本身是常量)
定义:
本质是一个常量,而用指针修饰它。指针常量的值是指针,这个值因为是常量,所以不能被赋值。

关键点:
1、它是个常量!
2、指针本身是常量,指向的地址不可以变化,但是指向的地址所对应的内容可以变化;
代码形式:

int* const p;

大话解释:
本质上一个常量,指针用来说明常量的类型,表示该常量是一个指针类型的常量。在指针常量中,指针自身的值是一个常量,不可改变,始终指向同一个地址。在定义的同时必须初始化。用法如下:

int a = 10, b = 20;
int * const p = &a;
*p = 30;      // p指向的地址是一定的,但内存地址空间中的内容可以修改

2、常量指针——指向“常量”的指针(const int *p, int const *p)

巧记:常量在指针前面, 程序语言: const在星号之前即可。

定义:
又叫常指针,可以理解为常量的指针,指向的是个常量

关键点:
1、常量指针指向的对象不能通过这个指针来修改,可是仍然可以通过原来的声明修改;
2、常量指针可以被赋值为变量的地址,之所以叫常量指针,是限制了通过这个指针修改变量的值;
3、指针还可以指向别处,因为指针本身只是个变量,可以指向任意地址; 
代码形式:

int const* p;  const int* p;

常量指针本质上是一个指针,常量表示指针指向的内容,说明该指针指向一个“常量”。在常量指针中,限制了通过这个指针修改变量的值,指针看起来好像指向了一个常量。用法如下:

int a = 10, b = 20;
const int *p = &a;
p = &b;    // 指针可以指向其他地址,但是内容不可以改变

3、例题
例题(1)

int main() {
    int m = 10;
    const int n = 20; // 必须在定义的同时初始化
 
    const int *ptr1 = &m; // 指针指向的内容不可改变
    int * const ptr2 = &m; // 指针不可以指向其他的地方
 
    ptr1 = &n; // 正确
    ptr2 = &n; // 错误,ptr2不能指向其他地方
 
    *ptr1 = 3; // 错误,ptr1不能改变指针内容
    *ptr2 = 4; // 正确
 
    int *ptr3 = &n; // 错误,常量地址不能初始化普通指针吗,常量地址只能赋值给常量指针
    const int * ptr4 = &n; // 正确,常量地址初始化常量指针
 
    int * const ptr5; // 错误,指针常量定义时必须初始化
    ptr5 = &m; // 错误,指针常量不能在定义后赋值
 
    const int * const ptr6 = &m; // 指向“常量”的指针常量,具有常量指针和指针常量的特点,指针内容不能改变,也不能指向其他地方,定义同时要进行初始化
    *ptr6 = 5; // 错误,不能改变指针内容
    ptr6 = &n; // 错误,不能指向其他地方
 
    const int * ptr7; // 正确
    ptr7 = &m; // 正确
 
    int * const ptr8 = &n;
    *ptr8 = 8;
 
    return 0;
}

例题(2)判断下面程序对错,并说明理由

int main()
{
char * const str = “apple”;
* str = “orange”;
cout << str << endl;
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”;
cout << str << endl;
getchar();
}
参考《程序员面试笔记》
例题3:自己亲自试验过,经历过
int main()
{
char * str = “apple”;
str = “orange”;
cout << str << endl;
getchar();
}
这个在vs2015上能够编译通过,但是在vs2017和vs2019上是不能编译通过的。
分析:因为"apple" 是存储在全局(静态变量)区,是只读的,不能修改。所以指向只读常量的指针必须声明为常量指针才能编译通过。

int main()
{
   const char * str = "apple";
    str = "orange";
    cout << str << endl;
    getchar();
}

这样写就能在vs2017和vs2019上编译通过了。

3、指向常量的常指针
定义:
指向常量的指针常量就是一个常量,且它指向的对象也是一个常量。

关键点:
一个指针常量,指向的是一个指针对象;
它指向的指针对象且是一个常量,即它指向的对象不能变化;
代码形式:

const int* const p;

你可能感兴趣的:(02C/C++语言基础知识)