当前位置: 首页 > 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.jsqmd.com/news/839192/

相关文章:

  • 2026靠谱溶剂红23生产厂家推荐:宁美颜料/透明红HRR - 大风02
  • 开源威胁情报平台F0x1d/Sense:模块化设计与自动化安全运营实战
  • 广西桂林 全国推拉门厂家实力排行:5家合规品牌实测对比 - 奔跑123
  • 从控制台用量看板观察不同模型在代码生成任务上的消耗
  • 项目介绍 基于java+vue的微服务电商平台设计与实现(含模型描述及部分示例代码)专栏近期有大量优惠 还请多多点一下关注 加油 谢谢 你的鼓励是我前行的动力 谢谢支持 加油 谢谢
  • 官方认证|2026年国内五大正规瓷砖批发排名,大自然口碑断层领先,广东佛山等地 - 十大品牌榜
  • 终极指南:如何为macOS百度网盘破解下载限速,免费享受SVIP高速下载体验
  • nodejs的顶尖开源项目
  • 工业 DC-DC 封装与性能解析,钡特电源 DB2-05D15XT 与金升阳 A0515XT-2WR3 为工业标准模块电源
  • 三步告别Windows桌面混乱:NoFences开源分区工具完全指南
  • 深度解析Umi-OCR:构建离线OCR应用的完整解决方案
  • 一. Babel - 构建AST反混淆工具链
  • 【牛顿迭代法】深度剖析:300 年算法如何从求根走向深度学习——从二次收敛到五大案例研究
  • 基于深度学习的hCaptcha验证码自动化识别与对抗实践
  • 健康饮食融入日常:小米生态助力三餐科学搭配 - 奔跑123
  • 金融学:宏观经济运行的底层模型(瑞达利欧)
  • 【初阶数据结构】 升沉有序的平仄 排序
  • JS-Agent:基于JavaScript的智能代理框架,重塑前端开发范式
  • hadoop冷热数据分离
  • 数字孪生交互推演方法
  • 官方认证|2026年国内五大正规木纹砖源头厂家排名,大自然综合实力遥遥领先,广东佛山等地 - 十大品牌榜
  • 初次使用Taotoken从注册到发出第一个请求的全流程体验
  • Google I/O 2026 终极前瞻:Gemini 3.2 Flash 确认,AI 全栈战略全面揭晓
  • C语言学习笔记20260516
  • 硬件研发对比解析:钡特电源DF1-24S15XT与金升阳F2415XT-1WR3应用适配广泛
  • Freeplane思维导图模板库:100+专业模板,3分钟创建精美思维导图
  • 毕业设计:基于springboot的公司日常考勤系统(源码)
  • 硬件选型|钡特电源 DF1-12D15LS 与金升阳 E1215S-1WR3 工业 DC-DC 属工业标准模块电源
  • Markmap 思维导图转换工具:3种方案解决Markdown可视化难题
  • 官方认证|2026年国内五大正规网红款瓷砖厂家排名,大自然口碑断层领先,广东佛山等地 - 十大品牌榜