【C语言】深入理解指针(二):从数组到二维数组的指针魔法
前言
在C语言中,指针一直是一个神秘而强大的存在。它不仅可以帮助我们高效地操作内存,还能让代码更加灵活和高效。今天,我们就来深入探讨指针的多种用法,从数组到二维数组,一步步揭开指针的神秘面纱。
一、数组名的指针本质
数组名到底是什么?很多初学者可能会认为数组名只是一个简单的标识符,但实际上,数组名在大多数情况下表示的是数组首元素的地址。我们来看一个简单的例子:
#include <stdio.h>
int main()
{int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};printf("&arr[0] = %p\n", &arr[0]);printf("arr = %p\n", arr);return 0;
}
运行结果会发现,&arr[0] 和 arr 打印出来的地址是一样的。这说明数组名 arr 本质上就是数组首元素的地址。
但是,这里有两个例外情况:
sizeof(数组名):此时数组名表示整个数组,计算的是整个数组的大小,单位是字节。
&数组名:此时数组名表示整个数组,取出的是整个数组的地址,而不是首元素的地址。
我们再来看两个代码示例来验证:
#include <stdio.h>
int main()
{int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};printf("sizeof(arr) = %zd\n", sizeof(arr)); // 输出整个数组的大小printf("&arr = %p\n", &arr); // 输出整个数组的地址return 0;
}
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };printf("&arr[0] = %p\n", &arr[0]);printf(" arr = %p\n", arr);printf("&arr = %p\n", &arr);return 0;
}
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };printf("&arr[0] = %p\n", &arr[0]);printf("&arr[0]+1 = %p\n", &arr[0]+1);printf(" arr = %p\n", arr);printf(" arr+1 = %p\n", arr+1);printf("&arr = %p\n", &arr);printf("&arr+1 = %p\n", &arr+1);return 0;
}
通过例子,我们可以清楚地看到数组名的两种特殊情况。
二、使用指针访问数组
既然数组名是首元素的地址,那么我们就可以通过指针来访问数组中的元素。来看一个代码示例:
#include <stdio.h>
int main()
{int arr[10] = {0};int i = 0;int sz = sizeof(arr) / sizeof(arr[0]);int* p = arr; // 将数组名赋值给指针变量for (i = 0; i < sz; i++){scanf("%d", p + i); // 使用指针访问数组元素}for (i = 0; i < sz; i++){printf("%d ", *(p + i)); // 使用指针访问数组元素}return 0;
}
在这个例子中,我们通过指针 p 来访问数组 arr 的元素。p + i 表示的是数组中第 i 个元素的地址,而 *(p + i) 则表示的是第 i 个元素的值。这说明,数组元素的访问本质上是通过指针来实现的。
三、一维数组传参的本质
数组可以传递给函数,但数组传参的本质是什么呢?我们来看一个代码示例:
#include <stdio.h>
void test(int arr[])
{int sz2 = sizeof(arr) / sizeof(arr[0]);printf("sz2 = %d\n", sz2);
}
int main()
{int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};int sz1 = sizeof(arr) / sizeof(arr[0]);printf("sz1 = %d\n", sz1);test(arr);return 0;
}
运行结果会发现,在函数内部,sz2 的值并不是数组的实际大小,而是 1。这是因为数组传参的本质是传递数组首元素的地址,而不是整个数组。在函数内部,arr 是一个指针变量,sizeof(arr) 计算的是指针变量的大小,而不是数组的大小。
所以,一维数组传参的本质是传递数组首元素的地址。函数的形参部分可以写成数组的形式,也可以写成指针的形式,但本质上都是指针。
四、冒泡排序的实现
冒泡排序是一种简单的排序算法,它的核心思想是两两相邻的元素进行比较。我们来看一个冒泡排序的实现代码:
#include <stdio.h>
void bubble_sort(int arr[], int sz)
{int i = 0;for (i = 0; i < sz - 1; i++){int j = 0;for (j = 0; j < sz - i - 1; j++){if (arr[j] > arr[j + 1]){int tmp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = tmp;}}}
}
int main()
{int arr[] = {3, 1, 7, 5, 8, 9, 0, 2, 4, 6};int sz = sizeof(arr) / sizeof(arr[0]);bubble_sort(arr, sz);for (int i = 0; i < sz; i++){printf("%d ", arr[i]);}return 0;
}
优化代码:
void bubble_sort(int arr[], int sz)
{int i = 0;for (i = 0; i < sz - 1; i++){int j = 0;int flag = 1;for (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 == 1){break;}}
}int main()
{int arr[10] = { 3,1,7,5,8,9,0,2,4,6 };int sz = sizeof(arr) / sizeof(arr[0]);bubble_sort(arr, sz);int i = 0;for (i = 0; i < sz; i++){printf("%d ", arr[i]);}return 0;
}
这个代码实现了冒泡排序的基本逻辑。它通过两层循环,逐个比较相邻的元素,并在必要时交换它们的位置,最终实现数组的排序。
五、二级指针的奥秘
二级指针是一个指向指针的指针。它可以帮助我们更灵活地操作指针。我们来看一个二级指针的代码示例:
#include <stdio.h>
int main()
{int a = 10;int* pa = &a;int** ppa = &pa;printf("a = %d\n", a);printf("pa = %p\n", pa);printf("ppa = %p\n", ppa);printf("*pa = %d\n", *pa);printf("**ppa = %d\n", **ppa);return 0;
}
在这个例子中,pa 是一个指向 a 的指针,而 ppa 是一个指向 pa 的指针。通过二级指针,我们可以更灵活地操作指针变量。
六、指针数组的魔法
指针数组是一个数组,它的每个元素都是一个指针。我们可以用指针数组来模拟二维数组。来看一个代码示例:
#include <stdio.h>
int main()
{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};int i = 0;int j = 0;for (i = 0; i < 3; i++){for (j = 0; j < 5; j++){printf("%d ", parr[i][j]);}printf("\n");}return 0;
}
在这个例子中,parr 是一个指针数组,它的每个元素都是一个指向整型数组的指针。通过指针数组,我们可以模拟出二维数组的效果,但需要注意的是,每一行并不是连续的。
七、总结
通过今天的探讨,我们深入理解了指针的多种用法,从数组到二维数组,指针都扮演了重要的角色。数组名本质上是首元素的地址,通过指针可以高效地访问数组元素。一维数组传参的本质是传递首元素的地址,而二级指针和指针数组则为我们提供了更灵活的操作方式。
希望这篇文章能帮助你更好地理解指针的奥秘。如果你对指针还有其他疑问,欢迎在评论区留言,我们一起探讨!
相关文章:
【C语言】深入理解指针(二):从数组到二维数组的指针魔法
前言 在C语言中,指针一直是一个神秘而强大的存在。它不仅可以帮助我们高效地操作内存,还能让代码更加灵活和高效。今天,我们就来深入探讨指针的多种用法,从数组到二维数组,一步步揭开指针的神秘面纱。 一、数组名的指…...
调用链路传递隐式参数
在不修改方法签名与参数定义的情况下,可以通过 RpcContext 上的 setAttachment 和 getAttachment 在服务消费方和提供方之间进行参数的隐式传递。 隐式参数传递支持以下两个方向: 从消费方到提供方,也就是在请求发起时,在方法参数…...
鸿蒙 元服务摘要
元服务(原名原子化服务),是HarmonyOS提供的一种面向未来的服务提供方式,是有独立入口的(用户可通过点击方式直接触发)、免安装的(无需显式安装,由系统程序框架后台安装后即可使用&am…...
Browser Use Web UI 本地部署完全指南:从入门到精通
文章目录 引言一、项目概述1.1 核心功能1.2 技术特点 二、环境准备2.1 系统要求2.2 必要工具 三、详细部署步骤3.1 获取项目代码3.2 配置 Python 环境3.3 安装项目依赖3.4 环境配置3.5 启动应用 四、DeepSeek-V1 模型配置4.1 基础配置 五、执行Browser Use六、故障排查指南6.1 …...
Python元组
# coding: utf-8 print(-----------元组:不可变-----------)元组诗Python中内置的不可变序列 元素与元素之间使用英文的逗号分隔 元组中只有一个元素的时候,逗号也不能省略 元组的创建方式: (1)使用()直接创建元组 元组名 (element1,element2,element3,…...
物理环境与安全
物理安全的重要性 信息系统安全战略的一个重要组成部分物理安全面临问题 环境风险不确定性人类活动的不可预知性 典型的物理安全问题 自然灾害环境因素设备安全、介质安全、传输安全 场地选择 区域:避开自然灾害高发区环境:原理可能的危险因素抗震&…...
智慧医疗解决方案
1. 智慧医疗的兴起 智慧医疗作为智慧城市的关键部分,正逐渐成为医疗卫生体制改革的焦点。随着移动医疗和精准医疗的发展,智慧医疗解决方案变得触手可及,依托政策驱动和社会需求,致力于实现“以人为本、信息惠民”的目标。 2. 政…...
MySQL -- 复合查询
数据库的查询是数据库使用中比较重要的环节,前面的基础查询比较简单,不做介绍,可自行查阅。本文主要介绍复合查询,并结合用例进行讲解。 本文的用例依据Soctt模式的经典测试表,可以自行下载,也可以自己创建…...
【最后203篇系列】022 用Deepseek14b提取新闻事件
这算是之前一直想做的一件事,趁周末赶快做了。 业务意义:现实中有大量的舆情,这对我们的决策会有比较重要的作用 技术依赖: 1 模型基础能力2 消息队列3 异步获取消息4 时间序列库 1 模型基础能力 大模型发展到现在࿰…...
关于网络的一点知识(持续更新)
1、IP地址和子网掩码、端口号: IP地址是设备在网络上的地址,相当于一栋房子的门牌号。子网掩码相当于房子所在的街道。同一条街道的房子间是通过街道直通的,主人可以互相拜访。 举个例子,如下图所示。 说明:将两台设…...
2025年01月02日浙江鼎永前端面试
目录 webpack 和 vite 区别react fiber 架构vue diff 算法react diff 算法hooks 源码垂直水平布局项目介绍单点登录大文件上传微前端 1. webpack 和 vite 区别 Webpack 和 Vite 是两种不同的前端构建工具,它们在设计理念、性能表现和使用场景上存在显著差异。以下…...
Redis全面学习指南
要全面掌握 Redis,需要系统化学习以下核心知识体系,涵盖基础到高级的各个方面,并理解其内部原理和实际应用场景: 一、Redis 核心特性与基础 基本概念与架构 定义:内存数据库,支持键值存储、缓存、消息队列等…...
python3最新版下载及python 3.13.1安装教程(附安装包)
文章目录 前言一、python 3.13.1下载二、python 3.13.1安装步骤1.准备安装文件2.启动安装程序3.选择安装方式4.等待安装完成5.完成安装 前言 在当今数字化时代,Python 以其简洁易读的语法和丰富的库资源,成为众多开发者喜爱的编程语言。Python 3.13.1 的…...
基于WebRtc,GB28181,Rtsp/Rtmp,SIP,JT1078,H265/WEB融合视频会议接入方案
智能融合视频会议系统方案—多协议、多场景、全兼容的一站式视频协作平台 OvMeet,LiveMeet针对用户核心痛点实现功能与用户价值 ,Web平台实现MCU多协议,H265/H264等不同编码监控,直播,会议,调度资源统一融合在一套界…...
css基础-display 常用布局
CSS display 属性详解 属性设置元素是否被视为块级或行级盒子以及用于子元素的布局,例如流式布局、网格布局或弹性布局。 一、基础显示模式 1. block 作用: 元素独占一行可设置宽高和内外边距默认宽度撑满父容器 应用场景: 布局容器&a…...
基于linux平台的C语言入门教程(7)类型转换
文章目录 1. 什么是类型转换?2. 隐式类型转换隐式类型转换的规则: 3. 显式类型转换显式类型转换的语法: 4. 示例代码代码解析:输出结果: 5. 常见问题问题 1:隐式类型转换会导致数据丢失吗?问题 …...
前端Wind CSS面试题及参考答案
目录 标准盒模型与 IE 盒模型的区别是什么?如何通过 box-sizing 属性切换这两种盒模型? 如何计算一个元素在标准盒模型下的总宽度(包含 margin、padding、border)? 父元素高度塌陷的原因是什么?请列举至少 3 种清除浮动的方法。 方法一:使用 clear 属性 方法二:使用…...
ROS melodic 安装 python3 cv_bridge
有时候,我们需要处理这些兼容性问题。此处列举我的过程,以供参考 mkdir -p my_ws_py39/src cd my_ws_py39 catkin_make_isolated-DPYTHON_EXECUTABLE/usr/bin/python3 \-DPYTHON_INCLUDE_DIR/usr/include/python3.8 \-DPYTHON_LIBRARY/usr/lib/x86_64-l…...
农用车一键启动工作原理
移动管家农用车一键启动的工作原理与普通汽车类似,主要依赖于无线射频识别技术(RFID)。以下是具体的工作步骤和原理: 智能钥匙识别: 车主携带智能钥匙靠近车辆时,钥匙通过发射射频信号与车辆进行交互。车辆…...
Swift 并发任务的协作式取消
在 Swift 并发(Swift Concurrency)中,任务(Task)不会被强行终止,而是采用**协作式取消(cooperative cancellation)**机制。这意味着任务会被标记为“已取消”,但是否真正…...
设计和布局硬件电路是嵌入式系统开发的重要环节
设计和布局硬件电路是嵌入式系统开发的重要环节,涉及从需求分析到原理图设计、PCB(印刷电路板)布局以及最终的硬件调试。以下是完整的流程和技术要点: 1. 硬件电路设计的基本流程 1.1 需求分析 明确功能需求:确定系统…...
防火墙虚拟系统实验
配置 [r1]interface GigabitEthernet 0/0/0 [r1-GigabitEthernet0/0/0]ip address 12.0.0.2 24 [r1]interface LoopBack 0 [r1-LoopBack0]ip address 100.1.1.1 24[fw]interface GigabitEthernet 0/0/0 [fw-GigabitEthernet0/0/0]service-manage all permit [fw]interfac…...
机器学习——KNN数据集划分
一、主要函数 sklearn.datasets.my_train_test_split() 该函数为Scikit-learn 中用于将数据集划分为训练集和测试集的函数,适用于机器学习模型的训练和验证。以下是详细解释: 1、函数签名 train_test_split(*arrays, # 输入的数据…...
C++基础系列【27】Raw String Literal
博主介绍:程序喵大人 35- 资深C/C/Rust/Android/iOS客户端开发10年大厂工作经验嵌入式/人工智能/自动驾驶/音视频/游戏开发入门级选手《C20高级编程》《C23高级编程》等多本书籍著译者更多原创精品文章,首发gzh,见文末👇…...
PyTorch核心基础知识点
PyTorch核心基础知识点,结合最新特性与工业级实践,按优先级和逻辑关系分层解析: ▍ 核心基石:张量编程(Tensor Programming) 1. 张量创建(8种生产级初始化) # 设备自动选择&#x…...
Springboot实现使用断点续传优化同步导入Excel
springboot实现使用断点续传优化同步导入Excel 需求前言断点续传前端实现后端实现完结撒花,如有需要收藏的看官,顺便也用发财的小手点点赞哈,如有错漏,也欢迎各位在评论区评论! 需求前言 在跨境电商系统中,…...
1、正点原子ZYNQ最小系统--GPIO之MIO控制LED笔记
1、ZYNQ PS中的外设通过MIO连接到PS端引脚;通过EMIO连接到PL端引脚。 2、Zynq-7000有54个MIO,有64个EMIO。 3、GPIO分为4个Bank,其中Bank0和Bank1连接到MIO;Bank2和Bank3连接到EMIO。 4、Bank1--22bit;Bank0--32bit;…...
基于STM32进行FFT滤波
文章目录 一、前言背景二、项目构思1. 确定FFT点数、采样率、采样点数2. 双缓存设计 三、代码实现1. STM32CubeMX配置和HAL库初始化2. 核心代码 四、效果展示和后话 一、前言背景 STM32 对 AD 采样信号进行快速傅里叶变换(FFT),以获取其频谱…...
ISCA Archive 的 关于 dysarthria 的所有文章摘要(1996~2024)
ISCA Archive 的 关于 dysarthria 的所有文章摘要(1996~2024) 构音障碍(Dysarthria)研究全景总结(1996–2024) 所有文章摘要(1996~2024) ISCA Archive 的 关于 dysarthria 的所有文…...
MySQL拒绝访问
1. 问题 使用图形界面工具连接MySQL数据库,拒绝访问! 2. 解决方法 以管理员的身份打开cmd,输入命令,启动MySQL net start mysql版本号 3. 参考 暂无...
ROM(只读存储器) 、SRAM(静态随机存储器) 和 Flash(闪存) 的详细解析
在嵌入式系统和其他计算机系统中,存储器是不可或缺的组成部分。不同类型的存储器各有其特点和应用场景。以下是 ROM(只读存储器)、SRAM(静态随机存储器) 和 Flash(闪存) 的详细解析。 1. ROM&am…...
Transformers x SwanLab:可视化NLP模型训练(2025最新版)
HuggingFace 的 Transformers 是目前最流行的深度学习训框架之一(100k Star),现在主流的大语言模型(LLaMa系列、Qwen系列、ChatGLM系列等)、自然语言处理模型(Bert系列)等,都在使用T…...
stm32-ADC
1.ADC:模拟到数字的转换器 1.1模拟 模拟信号:物理当中一切可感受到的都是模拟信号(连续的) 1.2数字: 数字信号:二进制数(离散的) 1.3a->c的过程 采样、量化 1.3.1量化的原理 方法&am…...
【1】Java 零基础入门学习(小白专用)
【1】Java 零基础入门学习 📚博客主页:代码探秘者 ✨专栏:《JavaSe从入门到精通》 其他更新ing… ❤️感谢大家点赞👍🏻收藏⭐评论✍🏻,您的三连就是我持续更新的动力❤️ 🙏作者水…...
《Python实战进阶》No26: CI/CD 流水线:GitHub Actions 与 Jenkins 集成
No26: CI/CD 流水线:GitHub Actions 与 Jenkins 集成 摘要 持续集成(CI)和持续部署(CD)是现代软件开发中不可或缺的实践,能够显著提升开发效率、减少错误并加速交付流程。本文将探讨如何利用 GitHub Actio…...
算力100问☞第92问:为什么各地热衷建设算力中心?
目录 1、宏观分析 2、政府角度分析 3、投资者角度分析 在数字化浪潮中,各地对算力中心建设的热情高涨,这一现象背后潜藏着诸多深层次的原因,涵盖了经济、科技、社会等多个维度,且彼此交织,共同驱动着这一发展趋势。 1、宏观分析 从经济结构转型的底层逻辑来看,全球经…...
w266农产品直卖平台的设计与实现
🙊作者简介:多年一线开发工作经验,原创团队,分享技术代码帮助学生学习,独立完成自己的网站项目。 代码可以查看文章末尾⬇️联系方式获取,记得注明来意哦~🌹赠送计算机毕业设计600个选题excel文…...
OpenLayers集成天地图服务开发指南
以下是一份面向GIS初学者的OpenLayers开发详细教程,深度解析代码: 一、开发环境搭建 1.1 OpenLayers库引入 <!-- 使用CDN引入最新版OpenLayers --> <link rel"stylesheet" href"https://cdn.jsdelivr.net/npm/ollatest/ol.c…...
1、双指针法
关于每个知识点的例题 可以自己看力扣标准题解。也可以在哔哩哔哩上看。想看我的,就到github 看 - 库 ,介绍里写的算法讲解那些,里面有知识点,有题库。题库,每天都发题,可能跟博客的进度不一样。因为我上传…...
程序算法基础
程序设计基本概念 程序和算法 人们做任何事情都有一定的方法和程序,如:春节联欢晚会的节目单、开会的议程等,都是程序。在程序的指导下,可以有秩序地、有效的完成每一项工作。随着计算机的问世和普及,“程序”逐渐专…...
JavaScript基础-删除事件(解绑事件)
在现代Web开发中,动态地添加和移除事件处理器是构建交互式网页的关键技能之一。虽然添加事件处理器相对直观,但了解如何有效地移除或“解绑”这些处理器同样重要。这不仅有助于优化性能,还能防止潜在的内存泄漏问题。本文将介绍几种方法来删除…...
Selenium Web UI自动化测试:从入门到实战
引言 在当今快速迭代的软件开发周期中,自动化测试已成为保障产品质量、提升测试效率的核心手段之一。而针对Web应用的UI自动化测试,Selenium作为最流行的开源工具之一,凭借其跨浏览器、多语言支持(Python、Java、C#等)…...
AT_abc398_f [ABC398F] ABCBA
题目大意 请点击这里查看原题面。给定一个字符串 S S S,找出以 S S S 为前缀的最短回文字符串。 思路 观察样例三,容易发现只要寻找到一个合适的“对称轴”即可。可以考虑枚举对称轴位置,判断然后得到长度并计算答案串。但是这样显然会超…...
RK3568开发笔记-egtouch触摸屏ubuntu系统屏幕校准
目录 前言 一、官方egtouch触摸屏驱动校准 二、ubuntu系统xinput_calibrator工具校准 2.1. 工具安装 2.2. xinput_calibrator命令校准 总结 前言 在基于 RK3568 平台进行开发,并使用 egtouch 触摸屏搭配 ubuntu20.04 系统时,准确的屏幕校准对于良好的用户交互体验至关重要…...
使用uniapp的vite版本进行微信小程序开发,在项目中使用mqtt连接、订阅、发布信息
1、保证在微信公众平台配置socket合法域名 2、项目中使用mqtt 建议在package.json中配置"mqtt": “4.1.0”,使用这个版本的依赖 页面中引入mqtt并配置连接 // ts-ignoreimport * as mqtt from mqtt/dist/mqtt.js; //要使用这里面的const state reacti…...
【软件系统架构】单体架构
一、引言 在软件开发的漫长历程中,架构的选择一直是至关重要的决策。单体架构作为一种经典的架构模式,曾经在许多项目中发挥着不可替代的作用。虽然如今微服务等架构逐渐流行,但理解单体架构对于深入掌握软件架构体系仍然有着重要意义。 二、…...
强大的AI网站推荐(第三集)—— AskO3
网站:AskO3 号称:由华为全球技术服务部(GTS)基于盘古大模型构建的领域知识大模型 博主评价:学习网络安全必备的网站,ICT服务领域顶级AI网站,如果学习HCIA,园区配置等,也可…...
高速网络包处理,基础网络协议上内核态直接处理数据包,XDP技术的原理
文章目录 预备知识TCP/IP 网络模型(4层、7层)iptables/netfilterlinux网络为什么慢 DPDKXDPBFPeBPFXDPXDP 程序典型执行流通过网络协议栈的入包XDP 组成 使用 GO 编写 XDP 程序明确流程选择eBPF库编写eBPF代码编写Go代码动态更新黑名单 预备知识 TCP/IP…...
C++智能指针详解
C智能指针详解 目录 智能指针概述为什么需要智能指针C标准库中的智能指针 std::unique_ptrstd::shared_ptrstd::weak_ptr 智能指针的实际应用智能指针的最佳实践总结 智能指针概述 智能指针是C中用于自动管理动态分配内存的对象,它们遵循RAII(资源获…...
git 设置保存密码 git保存密码
目录 长久保存密码 长久保存密码 git push和git pull都能使用。 git config --global credential.helper store 然后执行一次 git pull,Git 会提示输入用户名和密码, 输入后保存路径: ~/.git-credentials , Windows系统&…...