IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> const、常量指针、指向常量的指针 -> 正文阅读

[C++知识库]const、常量指针、指向常量的指针

有点迷迷糊糊的,不过好在,绕出来了

前提

首先要知道,定义了一个 int 类型的数据之后,它的地址的类型为 int* 类型。
定义了一个 const int 类型的数据,它的地址的类型是 const int* 类型。

指向常量的指针

什么叫指向常量的指针?
我们往往会定义const 来修饰的数据,比如:

const int n = 9; // 定义了一个整型常量 n

如果想使用一个指针来指向它,应该是什么类型的指针呢?首先说,下面的指针是不可以的

const int n = 9; // 定义了一个整型常量 n
int* p = &n; // 定义了一个int* 类型的指针
// "const int *" 类型的值不能用于初始化 "int *" 类型的实体

上面的例子中,定义了一个int* 类型的指针p,要用它来指向一个const int类型数据。是不能通过编译的。
这是因为,const int 类型的数据,不能让int* 类型的指针指向,即const int* 类型的地址数据,不可以赋值给int* 类型的变量。即 const int* -> int* 是不可以的。
正确方法:

const int n = 9; // 定义了一个整型常量 n
const int * p = &n; // 定义了一个const int* 类型的指针    正确写法
int const * q = &n; // 正确写法

上面两种写法都可以,都是const 要在 * 号之前。我比较习惯const 在 int 之前的写法。

注意,因为指针指向的是常量,是不可以修改常量的值的。即不可以通过指针修改内部的值,也不可以直接通过对 n 本身赋值来修改 n 的值。

const int n = 9; // 定义了一个整型常量 n
const int * p = &n; // 定义了一个const int* 类型的指针,指向 n
n = 188; // 错误
*p = 188; // 错误

因为 n 本身是const的,所以,其不可以更改,所以,无论是直接修改自身,还是通过指向它的指针修改,都是不可以的。

更进一步

如下所示

int n = 9; // 定义了一个普通整型数据 n
const int * p = &n; // 定义了一个const int* 类型的指针,指向 n

首先定义了一个普通的整型变量 n (这次没有使用const修饰),又定义了一个 const int* 类型的指针 p ,指向了 n。注意这次是使用一个 const int* 类型的数据,指向了一个普通的整型变量。换句话说,将一个int* 的地址,给了const int* 类型的指针变量。通过编译了,是可以的。
即将 int* -> const int *,是可以的。

为什么如此就可以,反过来就不行?答:从int*到const int *是从大范围到小范围,C++进行了隐式的转换,所以能够赋值成功。

前面的从const int * 到 int * 是从小范围到一个大范围,无法进行隐式类型转换,所以必须进行强制(显式)类型转换才能赋值成功就是这个原因了。

const int n = 199;
int * p = (int*)&n; // 正确,显式的进行强制类型转换
int * q = &n; // 错误

如果 n 是普通的 int 类型的数据,使用const int* 的指针 p 来指向它。那么仍然是无法通过指针来修改其中的数据,可能编译器认为 此时 p 指向的就是一个 const 的数据,所以不能通过指针修改。但是可以直接赋值修改 n ,毕竟 n 只是普通的数据。

int n = 0;
const int* p = &n;// 编译器进行了隐式的类型转换
*p = 9; // 错误。不可以通过指向常量的指针修改原数据,虽然这里 p 指向的是普通数据
n = 9;// 正确。因为 n 是普通数据,所以可以直接赋值修改

总结:

一个const int * 类型的指针,既可以指向普通的 int 类型的数据,又可以指向使用const 修饰的常量数据。此时的指针成为指向常量的指针。指针本身可以再指向别的数据。但是不可以通过指针去修改指向的数据。是否可以直接通过给数据赋值的形式,更改数据,就要看 该数据 究竟是不是真的const数据。

常量指针

何谓常量指针,如下:

int n = 0;
int * const p = &n;

可以看到,const 放在了 * 的后面。

int m = 9, n = 188;
int* const p = &m;
p = &n; // 错误。p不可以再指向别处
*p = 999; // 正确与否,要看 n 是不是const数据。此处正确

所以常量指针,即该指针只能指向一处。不能再指向别的位置。可以通过其修改指向的数据。

修改const类型的数据

const int n = 8;
int* const p = &n;
// "const int *" 类型的值不能用于初始化 "int *const" 类型的实体

n是const int 的数据,其地址类型为 const int*,而指针常量 p 是 int* const类型的,通不过编译。
可以使用强制类型转换解决。

const int n = 8;
int* const p = (int* const)&n; // 强制类型转换
*p = 7; // 

注意看,竟然通过指针修改了所指向的地址里面的数据。

#include <bits/stdc++.h>

using namespace std;

int main()
{
    const int n = 9;
    
    int* p = (int*)&n;

    *p = 10;

    printf("*p = %d\n",*p);
    // *p = 10
    
    printf("n = %d\n",n);
    // n = 9

    return 0;
}


上例中 n 为const 类型的变量,p 为指向它的一个普通指针变量(如果定义为const int* 类型的指针,是不能通过指针修改指向的内存中的数据的)。
通过 p 修改了内存中的值,但是 n 本身没有被修改。为什么?
这就是C++中的常量折叠:const变量(即常量)值放在编译器的符号表中,计算、访问时编译器直接从表中取值,省去了访问内存的时间,这是编译器进行的优化。n是const变量,编译器对n在预处理的时候就进行了替换。编译器只对const变量的值读取一次。所以访问n,得到的是9。n实际存储的值被指针p所改变。参考文章

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-03-11 21:57:07  更:2022-03-11 21:58:48 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 5:03:34-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码