【C语言】指针篇
目录
- C 语言指针概述
- 指针的声明和初始化
- 声明指针
- 初始化指针
- 指针的操作
- 解引用操作
- 指针算术运算
- 指针的用途
- 动态内存分配
- 作为函数参数
- 指针与数组
- 数组名作为指针
- 通过指针访问数组元素
- 指针算术和数组
- 数组作为函数参数
- 指针数组和数组指针
- 指针数组
- 数组指针
- 函数指针
- 函数指针的定义和声明
- 函数指针的初始化和使用
- 函数指针作为函数参数(回调函数)
- 函数指针数组
- 动态内存分配
- 概念
- 动态内存分配函数
- malloc 函数
- calloc 函数
- realloc 函数
- free 函数
- 示例代码
- 注意事项
- 常见错误与规避
- 内存泄漏(Memory Leak)
- 空指针引用(Null Pointer Dereference)
- 重复释放内存(Double Free)
- 越界访问(Buffer Overflow)
- realloc 使用不当
C 语言指针概述
在 C 语言中,指针是一个非常重要且强大的概念。它是一个变量,其值为另一个变量的地址,即内存位置的直接地址。可以把指针想象成一个特殊的变量,它存储的不是普通的数据,而是内存中某个变量的地址。通过指针,我们可以直接访问和操作该内存地址上存储的数据。
指针的声明和初始化
声明指针
在 C 语言中,声明指针的一般语法如下:
数据类型 *指针变量名;
其中,数据类型 表示该指针所指向的变量的数据类型,* 是指针声明符,用于表明这是一个指针变量。例如:
int *p; // 声明一个指向整型变量的指针p
float *q; // 声明一个指向浮点型变量的指针q
初始化指针
指针可以在声明时进行初始化,也可以在声明后再赋值。指针初始化时,需要将一个变量的地址赋给它。使用 & 运算符可以获取变量的地址。示例如下:
#include <stdio.h>int main() {int num = 10;int *p = # // 声明并初始化指针p,使其指向变量numprintf("变量num的地址: %p\n", &num);printf("指针p存储的地址: %p\n", p);return 0;
}
在上述代码中,&num 表示变量 num 的地址,将其赋给指针 p,这样 p 就指向了 num。
指针的操作
解引用操作
通过指针访问其所指向的变量的值,需要使用 * 运算符,这称为解引用操作。示例如下:
#include <stdio.h>int main() {int num = 10;int *p = #printf("变量num的值: %d\n", num);printf("通过指针p访问num的值: %d\n", *p);*p = 20; // 通过指针p修改num的值printf("修改后变量num的值: %d\n", num);return 0;
}
在上述代码中,*p 表示指针 p 所指向的变量的值,通过 *p = 20; 可以修改 num 的值。
指针算术运算
指针可以进行一些算术运算,如加法、减法等。指针算术运算的结果取决于指针所指向的数据类型的大小。示例如下:
#include <stdio.h>int main() {int arr[5] = {1, 2, 3, 4, 5};int *p = arr; // 指针p指向数组arr的首元素printf("p指向的元素的值: %d\n", *p);p++; // 指针p向后移动一个位置printf("p移动后指向的元素的值: %d\n", *p);return 0;
}
在上述代码中,p++ 使指针 p 向后移动一个 int 类型的位置,即移动了 sizeof(int) 个字节。
指针的用途
动态内存分配
C 语言提供了一些函数(如 malloc、calloc、realloc 等)用于动态分配内存,这些函数返回的是一个指针,通过指针可以访问和管理动态分配的内存。示例如下:
#include <stdio.h>
#include <stdlib.h>int main() {int *p = (int *)malloc(sizeof(int)); // 动态分配一个int类型的内存空间if (p == NULL) {printf("内存分配失败\n");return 1;}*p = 10;printf("动态分配内存中存储的值: %d\n", *p);free(p); // 释放动态分配的内存return 0;
}
作为函数参数
指针可以作为函数参数,通过指针传递参数可以在函数内部修改实参的值。示例如下:
#include <stdio.h>void swap(int *a, int *b) {int temp = *a;*a = *b;*b = temp;
}int main() {int x = 10, y = 20;printf("交换前: x = %d, y = %d\n", x, y);swap(&x, &y);printf("交换后: x = %d, y = %d\n", x, y);return 0;
}
在上述代码中,swap 函数接受两个指针作为参数,通过指针可以交换 x 和 y 的值。
指针与数组
在 C 语言中,指针和数组有着密切的联系。
数组名作为指针
在 C 语言里,数组名在大多数表达式中会被隐式转换为指向数组首元素的指针。也就是说,数组名代表了数组首元素的地址。
示例代码:
#include <stdio.h>int main() {int arr[5] = {1, 2, 3, 4, 5};// 打印数组首元素的地址printf("数组首元素的地址(使用&arr[0]): %p\n", &arr[0]);// 打印数组名代表的地址printf("数组名代表的地址: %p\n", arr);return 0;
}
在上述代码中,&arr[0] 是获取数组 arr 首元素的地址,而 arr 本身在这个表达式中也被解释为指向数组首元素的指针,所以它们的值是相同的。
通过指针访问数组元素
由于数组名可以当作指针使用,因此可以借助指针来访问数组中的元素。
示例代码:
#include <stdio.h>int main() {int arr[5] = {1, 2, 3, 4, 5};int *p = arr; // 指针p指向数组arr的首元素for (int i = 0; i < 5; i++) {// 通过指针访问数组元素printf("arr[%d] = %d\n", i, *(p + i));}return 0;
}
- <
相关文章:

【C语言】指针篇
目录 C 语言指针概述指针的声明和初始化声明指针初始化指针指针的操作解引用操作指针算术运算指针的用途动态内存分配作为函数参数指针与数组数组名作为指针通过指针访问数组元素指针算术和数组数组作为函数参数指针数组和数组指针指针数组数组指针函数指针函数指针的定义和声明…...

DeepSeek:如何通过自然语言生成HTML文件与原型图?
在当今快节奏的开发与设计环境中,快速生成HTML文件或原型图是每个开发者与设计师的迫切需求。虽然DeepSeek无法直接生成图片,但它却能够通过自然语言生成流程图、原型图以及交互式页面,甚至可以直接输出HTML代码。本文将详细介绍如何与DeepSe…...

数据结构与算法(两两交换链表中的结点)
原题 24. 两两交换链表中的节点 - 力扣(LeetCode) 给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。 示…...

语言模型作为零样本规划者:提取可执行知识以供具身代理使用
【摘要】 本文研究了预训练的语言模型(LLMs)能否被用来执行在交互式环境中的任务。作者发现,尽管LLMs在生成高阶任务的行动计划时可能无法做到完全精确定义,但通过适当提示,大型预训练语言模型可以分解高阶任务到中阶…...

Baklib智能推荐引擎驱动内容中台升级
智能推荐引擎技术架构 现代智能推荐系统的技术架构以语义分析算法为核心,通过自然语言处理技术解构内容特征,结合动态知识图谱实现信息实体关系的智能映射。该系统采用分层设计架构,基础层依托深度学习模型处理海量非结构化数据,…...

显示器长时间黑屏
现象 电脑启动后,进入登录界面前会随机黑屏,有时候十几秒,有时候几分钟 进入桌面后,长时间不操作电脑黑屏,移动鼠标,点击键盘后尝试点亮屏幕,也会消耗较长时间 尝试 重装系统,或者重新安装显卡,都能够恢复,但过段时间以后又出现黑屏情况 集成显卡,独立显卡都出现过 操作系统…...

顺序表与链表·续
引言 本文承接上文(顺序表与链表-CSDN博客),开始对链表的要点提炼。前文提到顺序表适合需要频繁随机访问且数据量固定的场景,而链表适合需要频繁插入和删除且数据量动态变化的场景。链表的引入弥补了顺序表在动态性和操作效率上的…...

nvidia驱动升级-ubuntu 1804
升级 1.从官网下载*.run驱动文件 2.卸载原始驱动 sudo /usr/bin/nvidia-uninstall sudo apt-get --purge remove nvidia-\* # 可能不需要加-\ sudo apt-get purge nvidia-\* # 可能不需要加-\ sudo apt-get purge libnvidia-\* # 可能不需要…...

【Linux】——初识操作系统
文章目录 冯-诺依曼体系结构操作系统shell 冯-诺依曼体系结构 我们现在所使用的计算机就是冯-诺依曼体系结构。 存储器就是内存。 由下图可知,寄存器最快,为啥不用寄存器呢? 因为越快价格就最贵,冯诺依曼体系结构的诞生…...

本地化deepseek
小白都能拥有自己的人工智能 1、我本地环境 系统:win10 cpu:i7(i7-12700),差不多就行 硬盘:500G+2T,可以不用这么大 显卡:七彩虹2060 12G ,够用了 我的配置最高也只能配上8B了, R1模型版本CPUGPU内存存储8B Intel Core i7/AMD Ryzen 7 及以上 无强制要求,有 4…...

利用可变参数模板,可打印任意参数和参数值。(C++很好的调式函数)
很酷的应用: (1) 如何获取可变参数名 代码例子: #define _test(...) (test_t(#__VA_ARGS__, __VA_ARGS__))template<typename... Args> void test_t(const char* names, Args... args) {std::cout << names <<…...

Yashan DB 体系结构
一、体系结构概况 1.1 线程管理 YashanDB采用多线程架构,线程分为两类: • 工作线程(Worker Threads):每个客户端连接到数据库实例时,会创建一个工作线程。工作线程负责处理客户端的SQL请求,执…...

测试工程师Deepseek实战之如何反向PUA它
问: 你是一名资深测试开发工程师 帮我设计一个提效工具,具有以下功能: 1.页面使用PYQT5设计,用两个输入控件,最好是日期类型的控件,第一个日期控件作为开始日期,第二个日期控件作为结束日期;前后…...

Windows系统中在VSCode上配置CUDA环境
前置步骤 安装符合GPU型号的CUDA Toolkit 配置好 nvcc 环境变量 安装 Visual Studio 参考https://blog.csdn.net/Cony_14/article/details/137510909 VSCode 安装插件 Nsight Visual Studio Code Editionvscode-cudacpp 安装 cmake 并配置好环境变量 注:Windows 端…...

React Native 0.76 升级后 APK 体积增大的原因及优化方案
在将 React Native 从 0.71 升级到 0.76 后,打包体积从 40 多 MB 增加到了 80 MB。经过一系列排查和优化,最终找到了解决方案,并将优化过程整理如下。 1. React Native 0.76 体积增大的可能原因 (1) 新架构默认启用 React Native 0.76 默认启用了 New Architecture(新架…...

pycharm找不到conda可执行文件
conda 24.9.2 在pycharm的右下角就可以切换python解释器了...

定时任务框架
常用定时任务框架 JDK 自带的 ScheduledExecutorService 适用于轻量级定时任务,基于线程池实现。API 简单,适用于小规模任务调度。 Quartz 强大的 Java 任务调度框架,支持 Cron 表达式、分布式集群、持久化等。适用于复杂调度场景࿰…...

ESP32S3读取数字麦克风INMP441的音频数据
ESP32S3 与 INMP441 麦克风模块的集成通常涉及使用 I2S 接口进行数字音频数据的传输。INMP441 是一款高性能的数字麦克风,它通过 I2S 接口输出音频数据。在 Arduino 环境中,ESP32S3 的开发通常使用 ESP-IDF(Espressif IoT Development Framew…...

利用后缀表达式构造表达式二叉树的方法
后缀表达式(逆波兰表达式)是一种将运算符放在操作数之后的表达式表示法。利用后缀表达式构造表达式二叉树的方法主要依赖于栈结构。 转换步骤 初始化 创建一个空栈。 遍历后缀表达式 对后缀表达式的每个符号依次处理: 遇到操作数 如果当前符…...

使用express创建服务器保存数据到mysql
创建数据库和表结构 CREATE DATABASE collect;USE collect;CREATE TABLE info (id int(11) NOT NULL AUTO_INCREMENT,create_date bigint(20) DEFAULT NULL COMMENT 时间,type varchar(20) DEFAULT NULL COMMENT 数据分类,text_value text COMMENT 内容,PRIMARY KEY (id) ) EN…...

YOLOv12本地部署教程——42%速度提升,让高效目标检测触手可及
YOLOv12 是“你只看一次”(You Only Look Once, YOLO)系列的最新版本,于 2025 年 2 月发布。它引入了注意力机制,提升了检测精度,同时保持了高效的实时性能。在保持速度的同时,显著提升了检测精度。例如&am…...

SQLAlchemy系列教程:如何防止SQL注入
SQL注入是一种常见的安全漏洞,它允许攻击者通过应用程序的SQL查询操纵数据库。使用ORM工具(如SQLAlchemy)提供的内置功能可以帮助减轻这些风险。本教程将指导您完成保护SQLAlchemy查询的实践。 了解SQL注入 当攻击者能够通过用户输入插入或操…...

1. 树莓派上配置机器人环境(具身智能机器人套件)
1. 安装树莓派系统 镜像下载地址(windows/Mac/Ubuntu),安装Pi5. 2. 环境配置(登录Pi系统) 2.1 启用 SSH From the Preferences menu, launch Raspberry Pi Configuration. Navigate to the Interfaces tab. Select Enable…...

基于SpringBoot的智慧停车场小程序(源码+论文+部署教程)
运行环境 • 前端:小程序 Vue • 后端:Java • IDE工具:IDEA(可自行选择) HBuilderX 微信开发者工具 • 技术栈:小程序 SpringBoot Vue MySQL 主要功能 智慧停车场微信小程序主要包含小程序端和…...

【从零开始学习计算机科学】数字逻辑(九)有限状态机
【从零开始学习计算机科学】数字逻辑(九)有限状态机 有限状态机状态机的表示方法有限状态机的Verilog描述有限状态机 有限状态机(简称状态机)相当于一个控制器,它将一项功能的完成分解为若干步,每一步对应于二进制的一个状态,通过预先设计的顺序在各状态之间进行转换,状…...

HarmonyOS Next~鸿蒙系统ArkCompiler跨平台编译技术的革新实践
HarmonyOS Next~鸿蒙系统ArkCompiler跨平台编译技术的革新实践 引言 在万物互联时代,操作系统对编译技术的需求已从单纯的代码转换演变为跨设备协同、高效资源调度与极致性能优化的综合挑战。华为鸿蒙系统(HarmonyOS)自主研发的ArkCompiler…...

AI大模型概念知多少
什么是大模型?什么是模型参数 1)现在的大模型要解决的问题,就是一个序列数据转换的问题: 输入序列 X X[x1 ,x2 ,...,xm ], 输出序列Y[y1 ,y2 ,…,yn ],X和Y之间的关系是:YWX。 “大模型”这个词…...

powermock,mock使用笔记
介于日本的形式主义junit4单体测试,特记笔记,以下纯用手机打出来,因为电脑禁止复制粘贴。 pom文件 powermock-module-junit1.7.4 powermock-api-mokcito 1.7.4 spring-test 8 1,测试类头部打注解 RunWith(PowerMockRunner.class…...

基于置换对称性的模型融合:实现凸盆地单盆地理论
【摘要】 一种合并神经网络模型的新方法,通过置换对称性来合并模型。即使在大规模的非凸优化问题中,神经网络损失景观似乎通常只有一个(几乎)封闭的盆地,这在很大程度上归因于隐藏层单元置换对称性。作者介绍了三种算法,用于将一个模型的单元置换为与参考模型对齐,从而…...

把握好自己的节奏, 别让世界成为你的发条匠
我见过凌晨两点还在回复工作群消息的职场妈妈,也见过凌晨三点抱着手机刷短视频的年轻人。 地铁站台的上班族永远在狂奔,连刚会走路的小孩都被早教班塞满了日程表。 现如今生活节奏快,像一只巨大的发条,每个人都被拧得紧紧的&#…...