十八款免费的软件下载/seo百度推广
1. 指针与const
在C语言中,const
关键字和指针一起使用时,可以创建对常量的引用,或者创建指向常量的指针。这对于保护重要数据不被意外修改以及提高程序的可读性和运行时的安全性非常有用。
1.1 const的基本用法
const
关键字用于声明一个变量为常量,这意味着一旦被初始化之后,它的值就不能被修改。
const int a = 10; // a是一个常量,不能被修改
// a = 20; // 错误:尝试修改常量的值
1.2 指针与const结合的用法
1.2.1 指向常量的指针
当const
关键字出现在星号*
的左边时,它意味着指针所指向的数据是不可修改的,但指针本身可以修改。
const int *ptr; // 指向整型常量的指针
int const *ptr; // 同上,与上一行等价
int value = 5;
ptr = &value; // 合法操作
//*ptr = 10; // 非法操作:不能通过ptr修改value的值
1.2.2 常量指针
当const
关键字出现在星号*
的右边时,它意味着指针本身是常量,即不能指向其他地址,但通过指针指向的数据可以被修改。
int *const ptr; // ptr是一个常量指针
int value1 = 5, value2 = 10;
ptr = &value1; // 非法操作:ptr不能指向其他地址
*ptr = 20; // 合法操作:可以通过ptr修改value1的值
1.2.3 指向常量的常量指针
当const
关键字同时出现在星号*
的左边和右边时,既指针所指向的数据也是常量,指针本身也是常量。
const int *const ptr = &value; // ptr是一个指向整型常量的常量指针
//ptr = &value2; // 非法操作:ptr不能指向其他地址
//*ptr = 10; // 非法操作:不能通过ptr修改value的值
总结
- 使用
const
可以定义不可变的常量。 const int *ptr
表示ptr
可以变,但ptr
指向的值不能变。int *const ptr
表示ptr
指向的值可以变,但ptr
本身不能变。const int *const ptr
表示ptr
和ptr
指向的值都不能变。- 适当使用
const
可以增加程序的安全性和可读性。
2. 指针数组
数组指针是指向数组的指针。理解数组指针对于高效地处理数组和执行复杂的内存操作非常重要。
2.1 数组与指针的基本关系
数组名本身就是一个指向数组第一个元素的指针。
int arr[5] = {1, 2, 3, 4, 5};
int *ptr = arr; // 等同于 int *ptr = &arr[0];
通过指针,我们可以访问和修改数组中的元素。
2.2 数组指针的声明
数组指针通常指向一个整个数组,而不仅仅是数组的第一个元素。声明数组指针的语法如下:
type (*arrayPtr)[size];
这里,type
是数组元素的类型,size
是数组的大小,arrayPtr
是指向数组的指针变量名。
示例:声明一个指向整型数组的指针
int (*ptrToArray)[5];
int array[5] = {1, 2, 3, 4, 5};
ptrToArray = &array;
2.3 通过数组指针访问数组元素
使用数组指针访问数组元素时,需要使用解引用操作符(*
)和下标。
// 假设 ptrToArray 指向一个包含 5 个整数的数组
for (int i = 0; i < 5; i++) {printf("%d ", (*ptrToArray)[i]);
}
在这个例子中,(*ptrToArray)
解引用数组指针,访问整个数组,然后我们使用下标[i]
访问数组的具体元素。
2.4 数组指针与多维数组
数组指针对于处理多维数组尤其有用,因为它可以简化对多维数组的访问和操作。
示例:声明一个指向二维整型数组的指针
int arr[2][3] = {{1, 2, 3}, {4, 5, 6}};
int (*ptrTo2DArray)[3] = arr; // 或者 &arr[0]
使用数组指针访问二维数组元素:
for (int i = 0; i < 2; i++) {for (int j = 0; j < 3; j++) {printf("%d ", ptrTo2DArray[i][j]);}printf("\n");
}
在这个例子中,我们没有使用(*ptrTo2DArray)
来解引用指针,因为当使用数组指针作为多维数组的指针时,可以直接使用下标来访问元素。
总结
- 数组指针是指向整个数组的指针。
- 声明数组指针时,需要指定数组的类型和大小。
- 使用数组指针可以方便地访问和操作数组元素,特别是在处理多维数组时。
- 数组指针在高级编程、动态内存分配以及函数参数传递中非常有用。
3. 函数指针
3.1 函数指针的声明
函数指针的声明包含了函数的返回类型、指针名称以及函数的参数列表。基本语法如下:
返回类型 (*指针变量名)(参数类型列表);
例如,声明一个指向返回类型为 int
,参数为两个 int
类型的函数的指针,可以这样写:
int (*funcPtr)(int, int);
3.2 使用函数指针
一旦声明了函数指针,就可以将它指向具有相应签名的任何函数。例如,如果有一个这样的函数:
int add(int a, int b) {return a + b;
}
可以这样将函数 add
赋值给之前声明的 funcPtr
:
funcPtr = add;
3.3 通过函数指针调用函数
通过函数指针调用函数的语法与直接调用函数类似,只不过函数名被替换为函数指针变量名。例如,使用 funcPtr
调用 add
函数:
int result = funcPtr(3, 5); // 调用add函数,参数为3和5
3.4 函数指针作为参数
函数指针最强大的用途之一是作为其他函数的参数。这允许你在运行时动态地改变函数的行为。例如:
void printOperationResult(int (*operation)(int, int), int a, int b) {int result = operation(a, b);printf("Result: %d\n", result);
}
这个 printOperationResult
函数接受一个函数指针 operation
作为参数,并用 a
和 b
作为参数调用它,然后打印结果。
3.5 返回函数指针的函数
函数也可以返回函数指针。声明这样的函数时,需要在返回类型前加上 (*)
和参数列表。例如:
int (*getOperation(char op))(int, int) {switch(op) {case '+':return add;// 可以添加更多的case来返回不同的函数指针default:return NULL;}
}
这个 getOperation
函数根据传入的操作符返回相应的函数指针。
函数指针数组是C语言中的一个高级特性,它允许你在一个数组中存储多个指向函数的指针。这种技术非常适合于实现函数表、回调函数列表或者状态机等。下面是一个关于如何使用函数指针数组的详细教程。
3.6 函数指针数组
3.6.1 函数指针数组的声明
函数指针数组的声明类似于普通数组的声明,但数组的元素类型是函数指针。基本语法如下:
返回类型 (*数组名[])(参数类型列表);
例如,声明一个指向返回类型为 int
,参数为两个 int
类型的函数的函数指针数组:
int (*operationArray[])(int, int);
3.6.2 初始化函数指针数组
在声明函数指针数组的同时,你可以初始化它,将数组中的每个元素指向具体的函数。例如:
int add(int a, int b) {return a + b;
}int subtract(int a, int b) {return a - b;
}// 初始化函数指针数组
int (*operationArray[])(int, int) = {add, subtract};
3.6.3 通过索引调用数组中的函数
你可以通过索引来访问函数指针数组中的元素,并通过这些函数指针调用函数。例如:
int result1 = operationArray[0](5, 3); // 调用add函数
int result2 = operationArray[1](5, 3); // 调用subtract函数
3.6.4. 遍历函数指针数组
你也可以遍历函数指针数组,对数组中的每个函数指针进行操作。例如:
int operations(int a, int b, int (*opsArray[])(int, int), int size) {for (int i = 0; i < size; i++) {printf("Operation %d result: %d\n", i, opsArray[i](a, b));}
}int main() {int (*operationArray[])(int, int) = {add, subtract};int size = sizeof(operationArray) / sizeof(operationArray[0]);operations(10, 5, operationArray, size);return 0;
}
3.6.5 函数指针数组作为函数参数
函数指针数组可以作为参数传递给其他函数,这在实现插件系统、事件处理系统时特别有用。传递函数指针数组作为参数的方法与传递普通数组类似。
3.7 回调函数
回调函数是一种在软件开发中常用的技术,它允许一个函数的行为被另一个函数在特定事件或条件发生时动态指定或“回调”。在C语言中,回调函数通常通过函数指针来实现。这种机制允许编写更通用、更灵活的代码,特别是在事件处理、异步编程和接口设计中非常有用。
3.7.1 定义回调函数
定义一个回调函数就是定义一个普通的函数,然后将这个函数的地址(通过函数名)传递给另一个函数,后者在适当的时刻调用这个回调函数。
例如,我们定义一个回调函数和一个接受这个回调函数作为参数的函数:
// 回调函数
void myCallback(int a) {printf("Callback called with %d\n", a);
}// 接受回调函数作为参数的函数
void performActionWithCallback(void (*callbackFunc)(int), int value) {// 在适当的时候调用回调函数callbackFunc(value);
}
3.7.2 使用回调函数
使用回调函数时,只需要将回调函数作为参数传递给另一个函数即可。例如:
int main() {// 调用performActionWithCallback,传递myCallback作为回调函数performActionWithCallback(myCallback, 5);return 0;
}
相关文章:

【C语言】(15)指针进阶
1. 指针与const 在C语言中,const关键字和指针一起使用时,可以创建对常量的引用,或者创建指向常量的指针。这对于保护重要数据不被意外修改以及提高程序的可读性和运行时的安全性非常有用。 1.1 const的基本用法 const关键字用于声明一个变…...

力扣精选算法100道—— 连续数组(前缀和专题)
连续数组(前缀和专题) 目录 🚩了解题意 🚩算法原理 ❗为什么hash设置成<0,-1>键值对 ❗与和为K的子数组比较hash的键值对 🚩代码实现 🚩了解题意 我们看到给定数组里面只有0和1,我们…...

flutter 国内源
Flutter 在中国由于网络原因,从官方默认的国外源下载Dart包和Flutter SDK可能会比较慢或者不稳定。为了加速依赖包的获取与Flutter SDK的安装,可以使用国内镜像源。以下是一些国内常用的Flutter和Dart包镜像源: 清华大学开源软件镜像站 Flu…...

第九个知识点:内部对象
Date对象: <script>var date new Date();date.getFullYear();//年date.getMonth();//月date.getDate();//日date.getDay();//星期几date.getHours();//时date.getMinutes();//分date.getSeconds();//秒date.getTime();//获取时间戳,时间戳时全球统一&#x…...

Android 车载应用开发之车载操作系统
一、前言 到 2030 年,全球电动汽车的销量将超过 7000 万辆,保有量将达到 3.8 亿辆,全球年度新车渗透率有望触及 60% 。这一数据来自国际能源署(IEA)发布的《全球电动汽车展望2023》。 市场趋势和政策努力的双加持下,新能源汽车来势凶猛,燃油车保有量逐年递减。此番景象…...

Qt PCL学习(文章链接汇总)
Qt PCL学习(一):环境搭建 Qt PCL学习(二):点云读取与保存 Qt PCL学习(三):点云滤波 Qt PCL学习(四):点云关键点 持续更新中…...

安卓动态链接库文件体积优化探索实践
背景介绍 应用安装包的体积影响着用户下载量、安装时长、用户磁盘占用量等多个方面,据Google Play统计,应用体积每增加6MB,安装的转化率将下降1%。 安装包的体积受诸多方面影响,针对dex、资源文件、so文件都有不同的优化策略&…...

[Java][算法 哈希]Day 01---LeetCode 热题 100---01~03
LeetCode 热题 100---01~03 ------->哈希 第一题 两数之和 思路 最直接的理解就是 找出两个数的和等于目标数 这两个数可以相同 但是不能是同一个数字(从数组上理解就是内存上不是同一位置) 解法一:暴力法 暴力解万物 按照需求 …...

【每日一题】LeetCode——链表的中间结点
📚博客主页:爱敲代码的小杨. ✨专栏:《Java SE语法》 | 《数据结构与算法》 | 《C生万物》 ❤️感谢大家点赞👍🏻收藏⭐评论✍🏻,您的三连就是我持续更新的动力❤️ 🙏小杨水平有…...

k8s 部署java应用 基于ingress+jar包
k8 集群ingress的访问模式 先部署一个namespace 命名空间 vim namespace.yaml kind: Namespace apiVersion: v1 metadata:name: ingress-testlabels:env: ingress-test 在部署deployment deployment是pod层一层封装。可以实现多节点部署 资源分配 回滚部署等方式。 部署的…...

深度学习技巧应用36-深度学习模型训练中的超参数调优指南大全,总结相关问题与答案
大家好,我是微学AI,今天给大家介绍一下深度学习技巧应用36-深度学习模型训练中的超参数调优指南大全,总结相关问题与答案。深度学习模型训练中的调优指南大全概括了数据预处理、模型架构设计、超参数优化、正则化策略和训练技巧等多个关键方面,以提升模型性能和泛化能力。 …...

“探索AJAX:前端与后端数据交互的利器“
前言 在现代Web开发中,前端与后端之间的数据交互是一个至关重要的环节。为了实现无需刷新页面的动态更新,AJAX(Asynchronous JavaScript and XML)作为一种强大的技术被广泛应用。 AJAX的原理 AJAX通过JavaScript和XMLHttpReque…...

【5G NR】移动通讯中使用的信道编解码技术
目录 一、引言 二、信道编解码技术概述 三、移动通讯中常用的信道编解码技术 四、优缺点分析与比较 五、未来发展趋势 六、结论 本文主要介绍了移动通讯中采用的信道编解码技术,由于在5G NR终端中,通常要兼容4G LTE通讯技术,所以4G LTE…...

用Python Tkinter打造的精彩连连看小游戏【附源码】
文章目录 连连看小游戏:用Python Tkinter打造的精彩游戏体验游戏简介技术背景MainWindow类:职责:方法:Point类: 主执行部分:完整代码:总结: 连连看小游戏:用Python Tkinter打造的精彩游戏体验 在丰富多彩的游戏世界中,…...

nvm安装node后,npm无效
类似报这种问题,是因为去github下载npm时下载失败, Please visit https://github.com/npm/cli/releases/tag/v6.14.17 to download npm. 第一种方法:需要复制这里面的地址爬梯子去下载(github有时不用梯子能直接下载,有…...

spring boot(2.4.x 开始)和spring cloud项目中配置文件application和bootstrap加载顺序
在前面的文章基础上 https://blog.csdn.net/zlpzlpzyd/article/details/136060312 spring boot 2.4.x 版本之前通过 ConfigFileApplicationListener 加载配置 https://github.com/spring-projects/spring-boot/blob/v2.3.12.RELEASE/spring-boot-project/spring-boot/src/mai…...

5-2、S曲线计算【51单片机+L298N步进电机系列教程】
↑↑↑点击上方【目录】,查看本系列全部文章 摘要:本节介绍S曲线的基本变换,将基本形式的S曲线变换成为任意过两点的S曲线,为后续步进电机S曲线运动提供理论支撑 一.计算目标 ①计算经过任意不同两点的S曲线方程 ②可调节曲线平…...

SQL 注入 - http头注入之UA头注入探测
环境准备:构建完善的安全渗透测试环境:推荐工具、资源和下载链接_渗透测试靶机下载-CSDN博客 一、http头注入介绍 HTTP头注入是一种网络安全攻击手段,它利用了Web应用程序对HTTP头的处理不当或缺乏充分的验证和过滤。在这种攻击中,攻击者通过修改HTTP请求头中的某些字段,…...

学习数据结构和算法的第5天
空间复杂度及其常见案例 空间复杂度 空间复杂度也是一个数学函数表达式,是对一个算法在运行过程中临时占用存储空间大小的量度。 空间复杂度不是程序占用了多少bytes的空间,因为这个也没太大意义,所以空间复杂度算的是变量的个数。空间复杂度…...

Android 11 访问 Android/data/或者getExternalCacheDir() root方式
前言: 需求要求安装三方应用ExternalCacheDir()下载下来的apk文件。 getExternalCacheDir() : /storage/emulated/0/Android/data/com../cache/ 获取访问权限 如果手机安卓版本为Android10的时候,可以在AndroidManifest.xml中添加下列代码 android:requestLegacyExt…...

Linux探秘之旅:透彻理解路径、命令与系统概念
目录 如何远程连接 远程登录简明指南 linux区别 1.严格区分大小写 2.linux的命令返回结果判断 3.如何查看网络信息 4.关于后缀名(Linux不关心文件后缀) 4.1 需要记忆的后缀 5.echo命令 6.linux一切皆文件 6.1比如磁盘的文件 6.2可执行文件 …...

哈希算法 c语言
#include <stdio.h> #include <stdlib.h> #include <string.h> // 哈希函数 unsigned int hash_function(const char *str) { unsigned int hash 0; while (*str) { hash (hash * 31 *str) % 1000; str; } return hash;…...

新版MQL语言程序设计:组合模式的原理、应用及代码实现
文章目录 一、什么组合模式二、为什么需要组合模式三、组合模式的实现原理四、组合模式的应用场景五、组合模式的代码实现 一、什么组合模式 组合模式是一种结构型设计模式,它允许将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和…...

代码随想录算法训练营第25天 | 216.组合总和III ,17.电话号码的字母组合
回溯章节理论基础: https://programmercarl.com/%E5%9B%9E%E6%BA%AF%E7%AE%97%E6%B3%95%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html 216.组合总和III 题目链接:https://leetcode.cn/problems/combination-sum-iii/ 思路: 本题就是在[1,2,3,4,5,6,7,…...

Rust 第一个rust程序Hello Rust️
文章目录 前言一、vscode 安装rust相关插件二、Cargo New三、vscode调试rustLLDB 前言 Rust学习系列。今天就让我们掌握第一个rust程序。Hello Rust 🦀️。 在上一篇文章我们在macOS成功安装了rust。 一、vscode 安装rust相关插件 以下是一些常用的 Rust 开发插件…...

高斯消去法 | LU分解 | PA=LU分解(MatLab)
一、问题描述 利用高斯消去法,LU 分解及PALU 分解求解非线性方程组。 二、实验目的 掌握高斯消去法、LU 分解、PALU 分解的算法原理;编写代码实现利用高斯消去法、LU 分解、PALU 分解来求解线性方程组。 三、实验内容及要求 1. 利用顺序高斯消去法求…...

Linux笔记之expect和bash脚本监听输出并在匹配到指定字符串时发送中断信号
Linux笔记之expect和bash脚本监听输出并在匹配到指定字符串时发送中断信号 code review! 文章目录 Linux笔记之expect和bash脚本监听输出并在匹配到指定字符串时发送中断信号1.expect2.bash 1.expect 在Expect脚本中,你可以使用expect来监听程序输出,…...

项目02《游戏-12-开发》Unity3D
基于 项目02《游戏-11-开发》Unity3D , 任务:实现场景怪物自动巡航 , 首先在场景中创建小球命名为路径点WayPoint0, 取消小球的碰撞器Collider, 再复制两个改名为WayPoint1 和 WayPoint2 , 在…...

记一次面试题
1.Php 私有化包(composer)的部署 1. 创建你的PHP包 确定你的包的功能和命名空间。 创建一个新的目录并初始化一个Git仓库。 使用composer init命令创建一个composer.json文件,并定义你的包名、版本、依赖等信息。 2. 开发并测试你的包 在本地…...

Rust入门2——随机数
文章目录 一、生成随机数二、比较两个数相等 简单列出两个Rust的小例子 一、生成随机数 在Cargo.toml的dependencies中引入rand,指定rand的版本 [dependencies] rand "^0.3.14"之后在主函数中调用rand函数,生成随机数 use rand::Rng; f…...