36 指针与 const 的多种搭配:指向常量的指针、常量指针、指向常量的常量指针、指针到指针的常量(涉及双重指针)

目录

1 指向常量的指针

1.1 概念

1.2 语法格式

1.3 声明与初始化

1.4 实际应用

1.4.1 保护数据

1.4.2 函数参数

1.4.3 字符串常量

2 常量指针

2.1 概念

2.2 语法格式

2.3 声明与初始化

2.4 实际应用

2.4.1 保护指针指向的地址

2.4.2 数组处理

2.4.3 函数参数

3 指向常量的常量指针

3.1 概念

3.2 语法格式

3.3 声明与初始化

3.4 实际应用

3.4.1 保护数据和指针

3.4.2 函数参数

4 指针到指针的常量

4.1 概念

4.2 语法格式

4.2.1 指向常量的指针的指针

4.2.2 指向常量的指针的常量指针

4.2.3 指向常量的常量指针的指针

4.3 声明与初始化

4.3.1 指向常量的指针的指针

4.3.2 指向常量的指针的常量指针

4.3.3 指向常量的常量指针的指针

4.4 实际应用

4.4.1 保护数据和指针

4.4.2 函数参数


1 指向常量的指针

1.1 概念

        指向常量的指针(Pointer to Const)是指其指向的值是常量(const 修饰的值),即这个指针所指向的存储单元的内容不能被修改指针本身仍然可以改变,即它可以指向不同的地址

1.2 语法格式

const 数据类型 *指针变量名;

        这里的 const 数据类型 表示指针所指向的数据是常量,而 * 表示指针。

1.3 声明与初始化

        “指向常量的指针” 可以在声明时进行初始化,也可以在声明后再进行初始化一旦初始化后,可以通过该指针访问数据,但不能修改数据    

const int a = 10;
int b = 20;// 声明并初始化一个指向常量的指针 p,使其指向变量 a
const int *p = &a;// 通过 p 访问 a 的值
printf("Value of a: %d\n", *p); // 正确,可以访问 a 的值// 通过 p 修改 a 的值
// *p = 15; // 错误,不能通过 p 修改 a// 改变 p 的指向
p = &b; // 正确,可以改变 p 的指向// 通过 p 访问 b 的值
printf("Value of b: %d\n", *p); // 正确,可以访问 b 的值// 通过 p 修改 b 的值
// *p = 25; // 错误,不能通过 p 修改 b

1.4 实际应用

1.4.1 保护数据

        “指向常量的指针” 可以确保指针所指向的数据不会被意外修改,从而提高代码的安全性和可维护性。

const int a = 10;void printValue(const int *p) {printf("Value: %d\n", *p);
}int main() {const int *p = &a;printValue(p); // 输出: Value: 10return 0;
}

        在这个例子中,printValue 函数的参数 p 是一个指向常量的指针,确保在函数内部不能通过 p 修改所指向的数据。 

1.4.2 函数参数

        在函数参数中使用 “指向常量的指针” 可以确保传递的指针所指向的数据不会被修改,从而避免意外的副作用。

const int a = 10;
const int b = 20;void swapValues(const int *p1, const int *p2) {// 交换两个指针所指向的数据// 这里假设我们有一个函数 swapInts 来交换两个整数// swapInts(*p1, *p2); // 错误,不能通过 p1 或 p2 修改数据
}int main() {const int *p1 = &a;const int *p2 = &b;swapValues(p1, p2); // 调用函数return 0;
}

        在这个例子中,swapValues 函数的参数 p1 和 p2 都是指向常量的指针,确保在函数内部不能修改 p1 和 p2 所指向的数据。 

1.4.3 字符串常量

        在处理字符串常量时,使用 “指向常量的指针” 可以确保字符串内容不会被修改

void printString(const char *str) {while (*str != '\0') {putchar(*str);str++;}putchar('\n');
}int main() {const char *str = "Hello, World!";printString(str); // 输出: Hello, World!// 尝试修改字符串内容// *str = 'h'; // 错误,不能通过 str 修改字符串内容return 0;
}

        在这个例子中,printString 函数的参数 str 是一个指向常量字符的指针,确保在函数内部不能修改字符串内容。 


2 常量指针

2.1 概念

        常量指针(Const Pointer)是指指针本身是一个常量,一旦初始化后,就不能再改变其指向的地址。这意味着指针所指向的内存地址是固定的,但指针所指向的数据是可以修改的

2.2 语法格式

数据类型 *const 指针变量名;

        这里的 *const 表示指针本身是常量,而数据类型表示指针所指向的数据的类型。

2.3 声明与初始化

        常量指针必须在声明时进行初始化,因为一旦初始化后,就不能再改变其指向的地址。

int a = 10;
int b = 20;// 声明并初始化一个常量指针 p,使其指向变量 a
int *const p = &a;// 通过 p 修改 a 的值
*p = 15; // 正确,可以修改 a 的值// 尝试改变 p 的指向
// p = &b; // 错误,不能改变 p 的指向

2.4 实际应用

2.4.1 保护指针指向的地址

        常量指针可以确保指针指向的地址不会被意外修改,防止指针的误操作(如错误地改变指针的指向),从而提高代码的安全性和可维护性。

2.4.2 数组处理

        在处理数组时,如果希望保护数组的起始地址不被改变,可以使用常量指针来指向数组的首元素。这样,即使函数内部对数组进行了处理,也不会改变数组的起始地址。

#include <stdio.h>// 函数声明,使用常量指针(仅指针本身是常量)作为参数
void printArray(int *const arr, int size);int main()
{int myArray[] = {1, 2, 3, 4, 5};int size = sizeof(myArray) / sizeof(myArray[0]);// 调用函数,传递数组和大小printArray(myArray, size);for (int i = 0; i < size; i++){printf("%d ", myArray[i]); // 100 100 100 100 100}return 0;
}// 函数定义,使用常量指针(仅指针本身是常量)作为参数
void printArray(int *const arr, int size)
{// 由于 arr 是 int *const,我们不能改变 arr 的值(即它指向的地址)for (int i = 0; i < size; i++){printf("%d ", arr[i]);// 1 2 3 4 5arr[i] = 100;}printf("\n");
}

        在这个示例中,printArray 函数保证不会改变 arr 的指向,但默认情况下仍然可以通过 arr 来读取数组的内容。 

2.4.3 函数参数

        在函数中,如果不希望函数内部改变传入指针的指向,可以将参数声明为常量指针。这样,函数内部就不能修改指针的值,但可以通过指针来访问和修改它所指向的数据。

void printArray(int *const arr, int size) {for (int i = 0; i < size; i++) {printf("%d ", arr[i]);}printf("\n");
}int main() {int array[] = {1, 2, 3, 4, 5};int size = sizeof(array) / sizeof(array[0]);printArray(array, size);return 0;
}

        在这个例子中,printArray 函数的参数 arr 是一个常量指针,确保在函数内部不会改变 arr 的指向。


3 指向常量的常量指针

3.1 概念

        指向常量的常量指针(Const Pointer to Const)是指指针本身是一个常量,同时指针所指向的数据也是一个常量。这意味着既不能通过该指针修改指针所指向的数据,也不能改变指针本身的指向

3.2 语法格式

const 数据类型 *const 指针变量名;

        这里的 const 数据类型 表示指针所指向的数据是常量,而 *const 表示指针本身是常量。

3.3 声明与初始化

        指向常量的常量指针必须在声明时进行初始化,因为一旦初始化后,就不能再改变其指向的地址,也不能通过该指针修改所指向的数据。

const int a = 10;
const int b = 20;// 声明并初始化一个指向常量的常量指针 p,使其指向变量 a
const int *const p = &a;// 通过 p 修改 a 的值
// *p = 15; // 错误,不能通过 p 修改 a// 尝试改变 p 的指向
// p = &b; // 错误,不能改变 p 的指向

3.4 实际应用

3.4.1 保护数据和指针

        指向常量的常量指针可以确保指针指向的数据不会被修改,同时指针本身的指向也不会被改变,从而提供更高的数据安全性和代码可维护性。

const int a = 10;
const int b = 20;void printValue(const int *const ptr) {printf("Value: %d\n", *ptr);
}int main() {const int *const p = &a;printValue(p); // 输出: Value: 10return 0;
}

        在这个例子中,printValue 函数的参数 ptr 是一个指向常量的常量指针,确保在函数内部既不能修改 ptr 所指向的数据,也不能改变 ptr 的指向。

3.4.2 函数参数

        在函数参数中使用 “指向常量的常量指针” 可以确保传递的指针不会在函数内部被重新赋值,同时确保指针所指向的数据不会被修改

const int a = 10;
const int b = 20;void swapPointers(const int * const ptr1, const int * const ptr2) {// 交换两个指针所指向的数据// 这里假设我们有一个函数 swapInts 来交换两个整数// swapInts(*ptr1, *ptr2); // 错误,不能通过 ptr1 或 ptr2 修改数据
}int main() {const int * const p1 = &a;const int * const p2 = &b;swapPointers(p1, p2); // 调用函数return 0;
}

4 指针到指针的常量

4.1 概念

“指针到指针的常量” 是指涉及双重指针的情况,其中指针本身或其指向的数据可以是常量。根据不同的组合,可以有以下几种情况:

  • 指向常量的指针的指针指针所指向的指针所指向的数据是常量
  • 指向常量的指针的常量指针指针本身是常量,同时它所指向的指针所指向的数据是常量
  • 指向常量的常量指针的指针指针所指向的指针本身是常量,同时它所指向的数据也是常量

4.2 语法格式

4.2.1 指向常量的指针的指针

const 数据类型 **指针变量名;

4.2.2 指向常量的指针的常量指针

const 数据类型 *const *指针变量名;

4.2.3 指向常量的常量指针的指针

const 数据类型 *const *const 指针变量名;

4.3 声明与初始化

4.3.1 指向常量的指针的指针

const int a = 10;
const int b = 20;
const int *p = &a; // p 指向 a
const int **pp = &p; // pp 指向 p// 通过 pp 修改 a 的值
// **pp = 15; // 错误,不能通过 pp 修改 a// 改变 p 的指向
p = &b; // 正确,可以改变 p 的指向// 改变 pp 的指向
// pp = &q; // 正确,可以改变 pp 的指向

4.3.2 指向常量的指针的常量指针

const int a = 10;
const int b = 20;
const int *p = &a; // p 指向 a
const int *const *pp = &p; // pp 指向 p// 通过 pp 修改 a 的值
// **pp = 15; // 错误,不能通过 pp 修改 a// 改变 p 的指向
// p = &b; // 错误,不能改变 p 的指向// 改变 pp 的指向
// pp = &q; // 正确,可以改变 pp 的指向

4.3.3 指向常量的常量指针的指针

const int a = 10;
const int b = 20;
const int * const p = &a; // p 指向 a
const int *const *const pp = &p; // pp 指向 p// 通过 pp 修改 a 的值
// **pp = 15; // 错误,不能通过 pp 修改 a// 改变 p 的指向
// p = &b; // 错误,不能改变 p 的指向// 改变 pp 的指向
// pp = &q; // 错误,不能改变 pp 的指向

4.4 实际应用

4.4.1 保护数据和指针

        “指针到指针的常量” 可以确保多级指针中的数据和指针不会被意外修改,从而提供更高的数据安全性和代码可维护性。

const int a = 10;
const int b = 20;void printValue(const int * const * const pp) {printf("Value: %d\n", **pp);
}int main() {const int * const p = &a;const int * const * const pp = &p;printValue(pp); // 输出: Value: 10return 0;
}

        在这个例子中,printValue 函数的参数 pp 是一个指向常量的常量指针的指针,确保在函数内部既不能修改 pp 所指向的指针 p,也不能修改 p 所指向的数据 a。

4.4.2 函数参数

        在函数参数中使用 “指针到指针的常量” 可以确保传递的指针不会在函数内部被重新赋值,同时确保指针所指向的数据不会被修改。

const int a = 10;
const int b = 20;void swapPointers(const int * const * const pp1, const int * const * const pp2) {// 交换两个指针所指向的数据// 这里假设我们有一个函数 swapInts 来交换两个整数// swapInts(**pp1, **pp2); // 错误,不能通过 pp1 或 pp2 修改数据
}int main() {const int * const p1 = &a;const int * const p2 = &b;const int * const * const pp1 = &p1;const int * const * const pp2 = &p2;swapPointers(pp1, pp2); // 调用函数return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/54336.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ASP.NET Core 创建使用异步队列

示例图 在 ASP.NET Core 应用程序中&#xff0c;执行耗时任务而不阻塞线程的一种有效方法是使用异步队列。在本文中&#xff0c;我们将探讨如何使用 .NET Core 和 C# 创建队列结构以及如何使用此队列异步执行操作。 步骤 1&#xff1a;创建 EmailMessage 类 首先&#xff0c…

1、Spring Boot 3.x 集成 Eureka Server/Client

一、前言 基于 Spring Boot 3.x 版本开发&#xff0c;因为 Spring Boot 3.x 暂时没有正式发布&#xff0c;所以很少有 Spring Boot 3.x 开发的项目&#xff0c;自己也很想了踩踩坑&#xff0c;看看 Spring Boot 3.x 与 2.x 有什么区别。自己与记录一下在 Spring Boot 3.x 过程…

Linux下的IO模型

阻塞与非阻塞IO&#xff08;Input/Output&#xff09; 阻塞与非阻塞IO&#xff08;Input/Output&#xff09;是计算机操作系统中两种不同的文件或网络通信方式。它们的主要区别在于程序在等待IO操作完成时的行为。 阻塞IO&#xff08;Blocking IO&#xff09; 在阻塞IO模式下…

详细介绍:API 和 SPI 的区别

文章目录 Java SPI (Service Provider Interface) 和 API (Application Programming Interface) 的区别详解目录1. 定义和目的1.1 API (Application Programming Interface)1.2 SPI (Service Provider Interface) 2. 使用场景2.1 API 的应用场景2.2 SPI 的应用场景 3. 加载和调…

PyGWalker:让你的Pandas数据可视化更简单,快速创建数据可视化网站

1、PyGWalker应用: 在数据分析的过程中,数据的探索和可视化是至关重要的环节,如何高效地将分析结果展示给团队、客户,甚至是公众,是很多数据分析师和开发者面临的挑战,接下来介绍的两大工具组合——PyGWalker与Streamlit,可以帮助用户轻松解决这个问题,即使没有复杂的代…

调用智谱AI,面试小助手Flask简单示例

文章目录 1.接入AI获取API密钥Python代码 2.小助手的实现流程3.Flask应用示例Python文件.pyindex.html运行Flask应用地址栏输入 http://localhost:5000/ 1.接入AI 获取API密钥 在智谱AI的官方网站上注册&#xff0c;右上角点击API密钥&#xff0c;新建并复制一个 API Key&…

个人网络安全的几个重点与防御

1 浏览器 firefox 这是第一选择 如果你真的不明白可以找找各个浏览器漏洞 mail 的危险的 来自与代理和漏洞 浏览器溢出漏洞 实时注意更新就可以 2 防火墙 大家都用windows 只需在 gpedit.msc 设置 但有什么未知漏洞就不得而知了 因为美国的计划问题 网络端口溢出漏洞 但…

流行前端框架Vue.js详细学习要点

Vue.js是一款流行的JavaScript前端框架&#xff0c;用于构建用户界面&#xff0c;特别是在构建交互式Web应用程序时表现出色。以下是Vue.js详细学习的一些要点&#xff1a; 1. Vue.js基础 定义与特点&#xff1a;Vue.js是一款渐进式JavaScript框架&#xff0c;提供响应式数据…

AI不可尽信

看到某项目有类似这样的一段代码 leaves : make([]int, 10) leaves leaves[:0]没理解这样的连续两行,有何作用? 初始化一个长度和容量都为10的切片,接着把切片长度设置为0 即如下demo: (在线地址) package mainimport "fmt"func main() {leaves : make([]int, 1…

MongoDB-aggregate流式计算:带条件的关联查询使用案例分析

在数据库的查询中&#xff0c;是一定会遇到表关联查询的。当两张大表关联时&#xff0c;时常会遇到性能和资源问题。这篇文章就是用一个例子来分享MongoDB带条件的关联查询发挥的作用。 假设工作环境中有两张MongoDB集合&#xff1a;SC_DATA&#xff08;学生基本信息集合&…

Flask-2

文章目录 请求全局钩子[hook]异常抛出和捕获异常abort 主动抛出HTTP异常errorhandler 捕获错误 context请求上下文(request context)应用上下文(application context)current_appg变量 两者区别&#xff1a; 终端脚本命令flask1.0的终端命令使用自定义终端命令 flask2.0的终端命…

基于深度学习的视频生成

基于深度学习的视频生成是一项极具前景的技术&#xff0c;旨在通过神经网络模型生成逼真的动态视频内容。随着生成对抗网络&#xff08;GANs&#xff09;、自回归模型、变分自编码器&#xff08;VAEs&#xff09;等深度学习模型的发展&#xff0c;视频生成技术已经取得了显著进…

⌈ 传知代码 ⌋ 将一致性正则化用于弱监督学习

&#x1f49b;前情提要&#x1f49b; 本文是传知代码平台中的相关前沿知识与技术的分享~ 接下来我们即将进入一个全新的空间&#xff0c;对技术有一个全新的视角~ 本文所涉及所有资源均在传知代码平台可获取 以下的内容一定会让你对AI 赋能时代有一个颠覆性的认识哦&#x…

查看 Git 对象存储中的内容

查看 Git 对象存储中的内容 ls -C .git/objects/<dir>ls: 列出目录内容的命令。-C: 以列的形式显示内容。.git/objects/<dir>: .git 是存储仓库信息的 Git 目录&#xff0c;objects 是其中存储对象的子目录。<dir> 是对象存储目录下的一个特定的子目录。 此…

mysql学习教程,从入门到精通,SQL 修改表(ALTER TABLE 语句)(29)

1、SQL 修改表&#xff08;ALTER TABLE 语句&#xff09; 在编写一个SQL的ALTER TABLE语句时&#xff0c;你需要明确你的目标是什么。ALTER TABLE语句用于在已存在的表上添加、删除或修改列和约束等。以下是一些常见的ALTER TABLE语句示例&#xff0c;这些示例展示了如何修改表…

H.264编解码 - I/P/B帧详解

一、概述 在H.264编解码中,I/P/B帧是一种常见的帧类型。以下是它们的解释: I帧(关键帧):也称为关键帧,它是视频序列中的第一个帧或每个关键时刻的第一个帧。I帧是完整的、自包含的图像帧,不依赖于其他帧进行解码。它存储了关键时刻的完整图像信息。 P帧(预测帧):P帧…

<STC32G12K128入门第十六步>获取NTP网络时间

前言 这里主要讲解如何通过NTP服务器获取网络时间。 一、NTP是什么? NTP全名“Network TimeProtocol”,即网络时间协议,是由RFC 1305定义的时间同步协议,用来在分布式时间服务器和客户端之间进行时间同步。 NTP基于UDP报文进行传输,使用的UDP端口号为123。使用NTP的目的…

2款.NET开源且免费的Git可视化管理工具

Git是什么&#xff1f; Git是一种分布式版本控制系统&#xff0c;它可以记录文件的修改历史和版本变化&#xff0c;并可以支持多人协同开发。Git最初是由Linux开发者Linus Torvalds创建的&#xff0c;它具有高效、灵活、稳定等优点&#xff0c;如今已成为软件开发领域中最流行…

some 蓝桥杯题

12.反异或01串 - 蓝桥云课 (lanqiao.cn) #include "bits/stdc.h" #define int long long using namespace std; char c[10000000]; char s[10000000]; int cnt,Ans,mr,mid; int maxi; int p[10000000],pre[10000000]; signed main() {ios::sync_with_stdio(0);cin.t…

如何使用EventChannel

文章目录 1 知识回顾2 示例代码3 经验总结我们在上一章回中介绍了MethodChannel的使用方法,本章回中将介绍EventChannel的使用方法.闲话休提,让我们一起Talk Flutter吧。 1 知识回顾 我们在前面章回中介绍了通道的概念和作用,并且提到了通道有不同的类型,本章回将其中一种…