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

深入理解指针3

1. 数组名的理解

首先给出一段代码

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表示arr[0]的地址

这时候有人会有疑问?数组名如果是数组首元素的地址,那下面的代码怎么理解呢

#include <stdio.h> int main() { int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }; printf("%d\n", sizeof(arr)); return 0; }

输出的结果是:40,如果arr是数组首元素的地址,那输出应该的应该是4/8才对,why?

其实数组名就是数组首元素(第一个元素)的地址是对的,但是有两个例外:

1.sizeof(数组名),sizeof中单独放数组名,这里的数组名表示整个数组,计算的是整个数组的大小, 单位是字节

2.&数组名,这里的数组名表示整个数组,取出的是整个数组的地址(整个数组的地址和数组首元素 的地址是有区别的)

除此之外,任何地方使用数组名,数组名都表示首元素的地址。

#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); 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; }

下面画图来理解

2. 使用指针访问数组

有了前面知识的支持,再结合数组的特点,我们就可以很方便的使用指针访问数组了。

int main() { int arr[10] = { 0 }; //给数组赋值为1-10 int* p = arr; int sz = sizeof(arr) / sizeof(arr[0]); for (int i = 0; i < sz; i++) { *p = i + 1; p++; } //打印 p = arr;// for (int i = 0; i < sz; i++) { printf("%d ", *(p + i)); //printf("%d ", *(arr + i)); } //arr[i] == *(arr+i) == *(p+i) return 0; }

3. 一维数组传参的本质

数组我们学过了,之前也讲了,数组是可以传递给函数的,这个小节我们讨论一下数组传参的本质。

void test(int arr[10]) { //不能使用参数部分的数组,来计算数组的元素个数 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);//arr就是首元素的地址==> &arr[0] return 0; }

从结果来看,test中的sizeof(arr)只有8个字节(x64环境下),这正好是地址的大小。

所以本质上是这样的,在有些地方也被称为数组降级,即数组降级为首元素地址

void test(int* arr)

完善后的代码

void test(int *arr, int sz) { int i = 0; for (i = 0; i < sz; i++) { //printf("%d ", *(arr + i)); printf("%d ", arr[i]); } }

4. 冒泡排序

https://visualgo.net/zh(该网站可可视化观察各种算法,若有兴趣可自行研究)

排序算法有很多,下面通过实现冒泡排序来理解一维数组传参

冒泡排序的核心思想就是:两两相邻的元素进行比较。

void bubble_sort(int* arr, int sz) { int i = 0; //确定趟数 for (i = 0; i < sz - 1; i++) { int flag = 1;//标记是否有序:假设已经有序 //一趟内部的比较 int j = 0; for (j = 0; j < sz - 1 - i; 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; } } }

即有n个数,就会进行n-1趟

这时只要设计一个标记变量flag便可以避免无效的循环

5. 二级指针

指针变量也是变量,是变量就有地址,那指针变量的地址存放在哪里?

int main() { int a = 10; int* pa = &a; //pa就是指针变量(一级指针变量) int** ppa = &pa;//ppa是指针变量(二级指针变量) return 0; }

如果想要通过二级指针访问a,需用**

printf("%d\n", **ppa);//100

6. 指针数组

指针数组的每个元素都是用来存放地址(指针)的

parr 是一个数组,数组有3个元素,每个元素的类型是 int* ;

7. 指针数组模拟二维数组

下面通过模拟二维数组,加深我们理解指针数组

int main() { int arr1[] = { 1,2,3,4 }; int arr2[] = { 5,6,7,8 }; int arr3[] = { 9,10,11,12 }; int* parr[3] = { arr1, arr2, arr3 }; for (int i = 0; i < 3; i++) { for (int j = 0;j < 4; j++) { printf("%d ", parr[i][j]); } printf("\n"); } }

parr[i] 是访问 parr 数组的元素, parr[i] 找到的数组元素指向了整型一维数组, parr[i] [j] 就是整型一维数组中的元素。 上述的代码模拟出二维数组的效果,实际上并非完全是二维数组,因为每一行并非是连续的。

http://www.rkmt.cn/news/1309894.html

相关文章:

  • 5分钟掌握XUnity自动翻译器:打破游戏语言障碍的终极指南 [特殊字符]
  • 广西桂林 全国推拉门厂家实力排行:5家合规品牌实测对比 - 奔跑123
  • MATLAB图像处理实战:用形态学开闭运算5分钟搞定椒盐噪声去除
  • 官方认证|2026年国内五大正规瓷砖批发排名,大自然口碑断层领先,广东佛山等地 - 十大品牌榜
  • 终极指南:如何为macOS百度网盘破解下载限速,免费享受SVIP高速下载体验
  • taotoken的tokenplan套餐如何帮助个人开发者更经济地使用大模型
  • Arm MMU-600内存管理单元原理与实战优化
  • 本地部署Gemma大模型:Ollama工具链与kessler/gemma-gem实践指南
  • Unity3D LineRenderer 从入门到精通:手把手教你绘制炫酷动态轨迹(附完整C#脚本)
  • 从 API Key 管理与审计日志功能看 Taotoken 的企业级安全支持
  • 健康饮食融入日常:小米生态助力三餐科学搭配 - 奔跑123
  • 独立开发者如何用Taotoken低成本试验不同模型的效果
  • Captain AI以视频运营破局!助Ozon商家抢占流量红利
  • DeepPCB:1500对工业级PCB缺陷图像数据集完全指南
  • 【网络编程2】- select
  • UAV Log Viewer:3分钟上手免费无人机日志分析工具
  • 官方认证|2026年国内五大正规网红款瓷砖厂家排名,大自然口碑断层领先,广东佛山等地 - 十大品牌榜
  • Freeplane思维导图模板库:100+专业模板,3分钟创建精美思维导图
  • 电视盒子变身家庭网络中心:TVBoxOSC热点功能终极指南
  • 技术研究者的开源知识库:用Git与Markdown构建结构化学习体系
  • 编程统计社区邻里活动参与数据,优化活动策划方案,拉近邻里关系,改善城市居民独居冷漠生活现状。
  • Datasheet学习1(Camera为例)
  • 基于Python的微信机器人框架copaw-wechat:插件化架构与自动化实践
  • 避坑指南:用TensorFlow 2.x和HuggingFace Transformers搞定中文NER,我踩过的这些坑你别再踩
  • 【计算机网络硬核指南】子网划分终极篇:定长+VLSM+超网三合一实战(3道大厂真题逐字节演算)
  • 2026 北京黄金回收如何抉择门店,安全靠谱首选收的顶 - 奢侈品回收测评
  • 第一次blog作业分析
  • HT7036计量芯片SPI通信与电压校准实战解析
  • RevokeMsgPatcher深度解析:Windows平台即时通讯消息保留技术完全手册
  • 硬件研发对比解析:钡特电源DF1-24S15XT与金升阳F2415XT-1WR3应用适配广泛