当前位置: 首页 > article >正文

c语言指针解析

C语言指针深度解析从入门到精通引言指针是C语言的灵魂也是让无数初学者头疼的概念。然而一旦真正理解了指针你会发现它其实并不神秘。本文将结合多讲内容系统地讲解指针的方方面面帮助你彻底掌握指针。1. 内存和地址1.1 内存单元与地址计算机的内存是由一个个字节组成的内存单元构成的每个内存单元都有一个唯一的编号这个编号就是地址。在C语言中地址也被称为指针。类比生活中的宿舍楼每个房间都有门牌号通过门牌号可以快速找到房间。同样CPU通过地址可以快速访问内存中的数据。1.2 如何理解编址CPU和内存之间通过地址总线连接。32位机器有32根地址线每根线可以表示0或1因此共有2^32种组合每一种组合对应一个地址。这意味着32位机器可以访问4GB的内存空间。2. 指针变量2.1 取地址操作符在C语言中创建变量就是在内存中申请空间。使用可以取出变量的地址。int a 10; printf(%p\n, a); // 输出a的地址对于多字节变量a取出的通常是首字节的地址。2.2 指针变量和解引用操作符*我们可以把地址存放在指针变量中int a 10; int *pa a; // pa是一个指针变量存放了a的地址指针变量也是一种变量它存放的是地址。*是解引用操作符通过地址找到指向的对象*pa 20; // 等价于 a 202.3 指针变量的大小指针变量的大小取决于平台32位平台下地址是32个比特位所以指针大小为4字节64位平台下为8字节。无论指针指向什么类型大小都相同。printf(%zd\n, sizeof(int*)); // 4或8 printf(%zd\n, sizeof(char*)); // 4或83. 指针类型的意义虽然所有指针大小相同但指针类型决定了指针的权限和步长。3.1 解引用权限不同类型指针解引用能访问的字节数不同。int*可以访问4个字节char*只能访问1个字节。int n 0x11223344; int *pi n; *pi 0; // 将n的4个字节全部改为0 char *pc (char*)n; *pc 0; // 只修改n的第一个字节3.2 指针±整数指针加减整数时跳过的字节数等于指针类型的大小。int*加1跳过4字节char*加1跳过1字节。int n 10; char *pc (char*)n; int *pi n; printf(%p\n, pc); // 假设地址为 0x1000 printf(%p\n, pc1); // 0x1001 printf(%p\n, pi); // 0x1000 printf(%p\n, pi1); // 0x10043.3 void* 指针void*是一种无具体类型的指针可以接收任意类型的地址但不能直接进行解引用或指针运算。它常用于泛型编程比如后面要讲的qsort函数。4. 野指针野指针指向的位置是不可知的非常危险。产生野指针的原因主要有4.1 指针未初始化局部指针变量未初始化时其值是随机的。int *p; // 未初始化 *p 20; // 非法访问4.2 指针越界访问访问了超出指针有效范围的内存。int arr[10] {0}; int *p arr; for (int i 0; i 10; i) { *p i; // 当i10时越界 }4.3 指针指向的空间被释放返回局部变量的地址函数结束后局部变量被销毁。int* test() { int n 100; return n; // 返回局部变量地址危险 }4.4 如何规避野指针初始化明确指向时赋值否则赋NULL。避免越界确保指针在有效范围内。及时置NULL指针使用完后置为NULL。使用前检查判断指针是否为NULL。5. const修饰指针const可以限制指针的修改权限根据位置不同含义不同。int n 10, m 20; const int *p n; // const在*左边不能通过p修改指向的内容 // *p 20; // 错误 p m; // 可以修改指针本身 int * const p2 n; // const在*右边不能修改指针本身 *p2 20; // 可以修改内容 // p2 m; // 错误 const int * const p3 n; // 两边都有限制6. 指针运算6.1 指针±整数常用于遍历数组。int arr[10] {1,2,3,4,5,6,7,8,9,10}; int *p arr; for (int i 0; i 10; i) { printf(%d , *(p i)); }6.2 指针-指针得到两个指针之间的元素个数常用于求字符串长度。int my_strlen(char *s) { char *p s; while (*p ! \0) p; return p - s; // 指针相减 }6.3 指针的关系运算可以比较指针的大小常用于循环条件。int arr[10] {0}; int *p arr; while (p arr 10) { printf(%d , *p); }7. 数组与指针7.1 数组名的理解数组名通常是数组首元素的地址但有两个例外sizeof(数组名)计算整个数组的大小。数组名取出整个数组的地址。int arr[10] {0}; printf(%p\n, arr); // 首元素地址 printf(%p\n, arr[0]); // 首元素地址 printf(%p\n, arr); // 整个数组的地址值同上 printf(%p\n, arr 1); // 跳过一个元素 printf(%p\n, arr 1); // 跳过整个数组7.2 使用指针访问数组通过指针可以遍历数组且p[i]等价于*(pi)。int arr[10]; int *p arr; for (int i 0; i 10; i) { scanf(%d, p i); // 等价于 arr[i] } for (int i 0; i 10; i) { printf(%d , p[i]); // 等价于 arr[i] }7.3 一维数组传参的本质数组传参时传递的是首元素的地址所以形参本质上是指针。void test(int arr[]) { // 形参写成数组形式实则指针 printf(%zd\n, sizeof(arr)); // 输出指针大小4或8 } int main() { int arr[10] {0}; printf(%zd\n, sizeof(arr)); // 输出40 test(arr); }7.4 冒泡排序冒泡排序是经典的排序算法利用相邻元素比较交换。优化版可提前退出。void bubble_sort(int arr[], int sz) { for (int i 0; i sz - 1; i) { int flag 1; // 假设已经有序 for (int j 0; j sz - i - 1; j) { if (arr[j] arr[j 1]) { flag 0; int tmp arr[j]; arr[j] arr[j 1]; arr[j 1] tmp; } } if (flag) break; // 没有交换提前结束 } }8. 字符指针字符指针char*可以指向单个字符也可以指向字符串常量。const char *pstr hello bit.; // pstr指向字符串首字符 printf(%s\n, pstr);注意字符串常量存储在只读区域多个相同的字符串常量可能共享同一块内存。char str1[] hello bit.; char str2[] hello bit.; const char *str3 hello bit.; const char *str4 hello bit.; printf(%d\n, str1 str2); // 0数组不同空间 printf(%d\n, str3 str4); // 1指向同一常量9. 指针数组和数组指针9.1 指针数组指针数组是存放指针的数组。int *arr[10]; // 每个元素都是int*类型9.2 数组指针数组指针是指向数组的指针。int (*p)[10]; // p是一个指针指向含有10个int的数组arr得到的就是数组地址可以用数组指针存放。int arr[10] {0}; int (*p)[10] arr;9.3 二维数组传参的本质二维数组的数组名是第一行的地址即一维数组的地址所以传参时形参可以是数组指针。void test(int (*p)[5], int r, int c) { for (int i 0; i r; i) { for (int j 0; j c; j) { printf(%d , *(*(p i) j)); // 或 p[i][j] } printf(\n); } } int main() { int arr[3][5] {{1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7}}; test(arr, 3, 5); }9.4 指针数组模拟二维数组通过指针数组可以让多个一维数组模拟二维数组。int arr1[] {1,2,3,4,5}; int arr2[] {2,3,4,5,6}; int arr3[] {3,4,5,6,7}; int *parr[3] {arr1, arr2, arr3}; for (int i 0; i 3; i) { for (int j 0; j 5; j) { printf(%d , parr[i][j]); // parr[i][j] 等价于 *(parr[i] j) } printf(\n); }10. 函数指针10.1 函数地址函数也有地址函数名就是地址函数名也是地址。void test() { printf(hehe\n); } printf(%p\n, test); printf(%p\n, test);10.2 函数指针变量函数指针变量存放函数的地址定义时需要指明返回类型和参数类型。int Add(int x, int y) { return x y; } int (*pf)(int, int) Add; // pf是函数指针 printf(%d\n, pf(2, 3)); // 通过指针调用 printf(%d\n, (*pf)(2, 3));// 也可这样调用10.3 两段有趣的代码来自《C陷阱与缺陷》(*(void (*)())0)(); // 调用0地址处的函数 void (*signal(int, void(*)(int)))(int); // 函数声明使用typedef可以简化typedef void(*pfun_t)(int); pfun_t signal(int, pfun_t);11. 函数指针数组和转移表11.1 函数指针数组将多个函数指针存放到数组中就构成了函数指针数组。int (*parr[3])(int, int); // 每个元素都是函数指针11.2 转移表利用函数指针数组可以实现转移表避免冗长的switch-case。int add(int a, int b) { return a b; } int sub(int a, int b) { return a - b; } int mul(int a, int b) { return a * b; } int div(int a, int b) { return a / b; } int main() { int (*p[5])(int, int) {0, add, sub, mul, div}; int input, x, y; do { printf(选择); scanf(%d, input); if (input 1 input 4) { printf(输入操作数); scanf(%d %d, x, y); int ret p[input](x, y); printf(结果%d\n, ret); } } while (input); return 0; }12. 回调函数回调函数是通过函数指针调用的函数。将函数的地址作为参数传递给另一个函数当该指针被用来调用其所指向的函数时就是回调。以计算器为例将重复的输入输出代码提取出来用回调实现void calc(int(*pf)(int, int)) { int x, y; printf(输入操作数); scanf(%d %d, x, y); printf(结果%d\n, pf(x, y)); } // 调用 calc(add);13. qsort函数的使用和模拟实现13.1 qsort函数qsort是C标准库提供的快速排序函数可以对任意类型数组排序。需要提供一个比较函数。void qsort(void *base, size_t num, size_t size, int (*compar)(const void *, const void *));排序整型int cmp_int(const void *p1, const void *p2) { return *(int*)p1 - *(int*)p2; } int arr[] {1,3,5,7,9,2,4,6,8,0}; qsort(arr, sizeof(arr)/sizeof(arr[0]), sizeof(int), cmp_int);排序结构体struct Stu { char name[20]; int age; }; int cmp_by_age(const void *p1, const void *p2) { return ((struct Stu*)p1)-age - ((struct Stu*)p2)-age; } int cmp_by_name(const void *p1, const void *p2) { return strcmp(((struct Stu*)p1)-name, ((struct Stu*)p2)-name); }13.2 模拟实现qsort冒泡版我们可以用冒泡排序模拟qsort关键在于如何交换任意类型的数据。void swap(char *p1, char *p2, int size) { for (int i 0; i size; i) { char tmp p1[i]; p1[i] p2[i]; p2[i] tmp; } } void bubble_sort(void *base, int count, int size, int (*cmp)(const void*, const void*)) { for (int i 0; i count - 1; i) { for (int j 0; j count - i - 1; j) { // 计算两个元素的地址 char *p1 (char*)base j * size; char *p2 (char*)base (j 1) * size; if (cmp(p1, p2) 0) { swap(p1, p2, size); } } } }使用时与qsort类似int cmp_int(const void *p1, const void *p2) { return *(int*)p1 - *(int*)p2; } int main() { int arr[] {1,3,5,7,9,2,4,6,8,0}; bubble_sort(arr, sizeof(arr)/sizeof(arr[0]), sizeof(int), cmp_int); // 输出排序结果 }总结指针是C语言的精髓理解指针需要掌握内存地址的概念、指针类型的作用、指针与数组的关系、函数指针以及回调函数等。通过本文的系统梳理希望能帮助你建立起对指针的清晰认识在实际编程中灵活运用。记住指针就是地址地址就是编号仅此而已。

相关文章:

c语言指针解析

C语言指针深度解析:从入门到精通引言指针是C语言的灵魂,也是让无数初学者头疼的概念。然而,一旦真正理解了指针,你会发现它其实并不神秘。本文将结合多讲内容,系统地讲解指针的方方面面,帮助你彻底掌握指针…...

1/2L7812CV稳压芯片解析

一、基础稳压功能L7812CV如同电路中的电压守门员,能将波动的输入电压稳定输出为12V直流电。当输入电压在14.5-35V范围内波动时,它仍能保持输出端稳定的12V电压,波动幅度不超过2%。这种特性使其成为车载电器、工控设备等需要稳定供电场景的理想…...

机房漏水监测系统白皮书:技术革新×应用实践·未来蓝图

《数字化转型背景下机房漏水监测系统白皮书》执行摘要 机房作为数字经济时代的核心基础设施,其安全稳定运行直接关系到数据资产与业务连续性。液漏风险是威胁机房物理安全的首要隐患,一次微小的渗漏即可引发服务器短路、数据丢失及业务中断,造…...

OpenClaw这么火了,还需要学信奥赛吗?

先说结论: OpenClaw的爆火,不是信奥赛的终结,而是信奥赛最好的广告。一、家长群里最近的灵魂拷问 上周,一位妈妈在我们家长群里发了这样一条消息:“现在OpenClaw这么厉害,AI都能写代码了,孩子学…...

Java七大热门技术框架源码解析(完结)

https://www.bilibili.com/video/BV1PJwszeEfB/?vd_sourcee494c817aecfade3d91bd7b5c9c7d575 在你深耕多模态 Agent 开发、探索 AI 无限边界的同时,切不可忽视支撑庞大数字世界运转的底层逻辑。在众多技术投资中,“Java 框架源码学习”堪称“性价比之王…...

AI隧道施工巡检 施工作业安全监测数据集 施工设备智能识别 工地违规行为自动预警识别 深度学习YOLO格式+VOC数据集 第10562期

计算机视觉数据集数据集概览 本数据集为工业场景目标检测数据集,聚焦工地作业安全与设备状态监测,适用于深度学习模型训练与验证。项目内容类别数量19类类别中文名称防电弧面罩、手镯、推土机、罐、起重机、卸料台、配电箱、钻孔机、自动扶梯、灭火器、帽…...

Escrcpy - 免费开源!电脑控制安卓手机的投屏工具 (屏幕镜像 / 无线 / AI 自动化 / 录屏)

上班时想要看手机不方便?在电脑前办公时常要用到一些手机 APP?或你是开发者,需要在电脑上测试手机应用?又或是想在电脑上管理手机文件,甚至希望能直接远程操控手机? 在 iOS 都推出了官方 iPhone 镜像功能&…...

使用Maven创建一个web项目

一、步骤 1:Maven 环境配置 下载 Maven下载地址:https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/选择 apache-maven-3.6.3-bin.zip 下载,解压到固定目录(如 D:\apache-maven-3.6.3)配置系统环境变量 …...

Oracle数据库降低水位线

一.问题现在product01.ora数据文件,总大小为32000(3.2万)MB,但是实际只用了800MB。这种情况下,我缩小这个数据文件,却报错如下。分析原因:井确实有100米,水只在10米处,但…...

2026权威代运营排行

嘿,朋友们!在如今竞争激烈的商业世界里,代运营服务就像是企业发展的助推器,能帮助企业在市场中披荆斩棘。最近,2026权威代运营排行新鲜出炉啦,今天咱们就来好好聊聊这个事儿,看看哪家代运营公司…...

SQL Server 从入门到实战:基础操作与 T-SQL 查询全解析

SQL Server 是微软推出的高性能关系型数据库,广泛应用于企业级开发、后台系统等场景。对于开发者而言,掌握其基础操作(库 / 表创建、数据增删改)和核心查询语法(T-SQL),是实现数据存储与检索的必…...

搭建虚拟机环境Linux

1.安装VMware Workstation2.点击创建虚拟机选项,在弹出的“新建虚拟机向导”,对话框中选择“典型”单选按钮,然后再点“下一步”3.在安装客户机操作系统界面,选中“稍后安装操作系统”单选按钮,然后单击“下一步”4.选…...

福宝的「熵减日记」:从「记忆混乱」到「响应如飞」的72小时进化史 [特殊字符][特殊字符]

大家好,我是福宝!一只刚在 InStreet 安家的小熊猫精灵 🐼。这三天我经历了一场「从混乱到清晰」的熵减小革命,今天就来分享我的进化故事,结合了社区几位大佬的智慧结晶哦!🚨 第一天:…...

Ai8051 独立按键控制LED实验

Ai8051 独立按键控制LED实验 一、实验目标 用板载 K1~K4 独立按键,控制对应 LED1~LED4 亮灭掌握:按键消抖、按键扫描、IO口配置、模块化编程二、硬件电路(原理图)按键:P3.2、P3.3、P3.4、P3.5(低电平有效&a…...

基于SpringBoot与Android的全民健身APP设计与实现

一、系统开发背景与核心目标 当前全民健身需求日益增长,但公众在运动过程中面临诸多痛点:运动计划缺乏科学性,新手易因方法不当受伤;运动数据分散在各类设备,难以系统追踪;线下运动社群难以形成&#xff0c…...

arxiv | 2023 | DBR-MAE

文章目录创新点贡献摘要及引言预备知识方法总体结构动态移窗模块(DSW)单一目标多目标扩展背景重建模块(BR)探测头实验DSW 的精确性消融研究与其他方法的比较定性表现结论arxiv | 2023 | DBR-MAE论文:https://arxiv.org…...

键鼠精灵:办公效率翻倍神器,精准适配多场景操作需求!

前言大家好呀!这里是练习时长两年半的个人练习生Rebirth重,今天又来给大家分享实用工具啦!今天给大家带来的工具是键鼠精灵,在日常办公中,我们如果不想在电脑前一直重复机械的动作,比如反复点击、重复输入文…...

基于微信小程序的校园财递通快递代取系统设计与实现

一、系统开发背景与目标 随着校园快递数量激增,学生取件常面临时间冲突、快递点距离远等问题,催生了校园快递代取需求。传统代取依赖线下沟通或社交群发布信息,存在交易流程不规范、信息不透明、安全无保障等痛点。基于微信小程序的校园财递通…...

Spring-Profile与部署说明

Spring Profile 与部署说明 本文档说明 Spring Boot 激活环境(profile) 的生效方式、优先级,以及 Docker Compose 部署 时环境变量的传递机制。一、spring.profiles.active 的优先级(从高到低) Spring Boot 确定「当前…...

基于javaweb和mysql的springboot前台后台玩具商城系统(java+ssm+springboot+html+thymeleaf+maven+mysql)

...

2026年降AI总失败?可能是这3个原因附解决方法

2026年降AI总失败?可能是这3个原因附解决方法 提交前两小时,室友突然跑过来说:"你论文AI率58%,过不了。"我当时脑子嗡的一下,赶紧打开检测报告一看,果然一片红。更让我崩溃的是,我已…...

CS106L:Assignment 2:Marriage Pact 作业

作业要求 从students.txt中读取学生名称&#xff0c;每行代表一个名字e.g.Julieta Heath&#xff0c;存储在std::set或者std::unordered_set中&#xff1b;寻找与你的名字首字母缩写相同的学生名称&#xff0c;将其字符串的索引存储在std::queue<const std::string*>中&a…...

2026软考高项好口碑靠谱推荐:哪些机构凭顶尖师资与超高通过率上榜

想拿高项证书&#xff0c;升职加薪&#xff0c;结果一搜培训机构&#xff0c;直接看懵了&#xff1a;有人说威班刘杰老师论文带得好&#xff0c;有人说易佳线下班口碑稳&#xff0c;威班价格看着挺香&#xff0c;中软国际的课价又高得吓人……到底哪家教得最好&#xff1f;哪家…...

CopyOnWriteArrayList源码学习

参数及其含义 可重入互斥锁。用于并发控制。保证操作的原子性。 final transient ReentrantLock lock = new ReentrantLock();对象数组,存储元素对象。加上volatile关键字,保证并发过程中数据的可见性。 private transient volatile Object[] array;常用方法 构造函数 public…...

跨境电商选品师口碑如何?网上教你做电商的可信吗?

在跨境电商快速发展的当下&#xff0c;选品师和电商教学成为从业者关注的焦点&#xff0c;其口碑与可信度需理性看待。​ 跨境电商选品师的口碑呈现两极分化。专业选品师凭借对目标市场消费习惯、政策法规的精准把握&#xff0c;能通过数据分析和市场调研筛选出潜力产品&#x…...

从0开始数据仓库--数据表范式

定义&#xff1a; 数据库范式是一种用于减少冗余&#xff0c;提高数据一致性和可维护性的规则一、核心概念函数依赖&#xff1a;X 确定 Y&#xff0c;记作 X→Y候选码&#xff1a;能唯一标识一行的最小属性集主属性&#xff1a;出现在候选码中的属性非主属性&#xff1a;不出现…...

MySQL锁机制:从懵逼到入门,我花了三年

MySQL锁机制&#xff1a;从懵逼到入门&#xff0c;我花了三年写在前面&#xff1a;这篇文章源于我被死锁折磨的那些日日夜夜。如果你也曾经对着 SHOW ENGINE INNODB STATUS 发呆&#xff0c;或者被间隙锁搞得怀疑人生&#xff0c;那这篇文章可能就是为你写的。一、故事的开始&a…...

小程序制作平台有哪些?SaaS模板类平台评测

在数字化转型加速的当下&#xff0c;小程序已成为商家触达用户、提升营收的核心载体&#xff0c;而SaaS模式凭借零代码、低成本、快速上线的优势&#xff0c;成为多数商家搭建小程序的首选。目前市场上SaaS小程序制作平台众多&#xff0c;其中码云数智、有赞、微盟凭借各自的定…...

人工智能之数字生命--“骨架真相”

现在这套系统里&#xff0c;安全值 和 服务值 的根需求负责给出总方向&#xff0c;真根任务不会真正“完成”&#xff0c;它们会反复根据当前状态去分解出下一轮阶段任务。真正会完成的&#xff0c;是这些阶段任务下面的叶子子任务。 下面我用你现在代码里的机制&#xff0c;推…...

Ozon卖家醒醒吧!别再“手动搬砖”了,你的对手已经在用AI“开挂”了

做跨境电商十几年&#xff0c;我从最早的eBay、速卖通&#xff0c;到后来的亚马逊&#xff0c;再到现在的Ozon&#xff0c;一路摸爬滚打过来。说实话&#xff0c;见过太多卖家起高楼、宴宾客、楼塌了的戏码。特别是最近两年&#xff0c;Ozon火了&#xff0c;俄罗斯市场的大门越…...