C 深入指针(3)

目录

一、关于数组名

1 数组名的理解

2 数组名 与 &数组名 的区别

二、使用数组访问指针

三、一维数组传参的本质

四、二级指针

五、指针数组

六、指针数组模拟二维数组 


一、关于数组名

1 数组名的理解

//VS2022 x64
#include <stdio.h>
int main()
{int arr[5] = { 1,2,3,4,5 };printf("%p\n", &arr[0]);	//%p 打印地址printf("%p\n", arr);return 0;
}
//输出
//00000005302FFC78
//00000005302FFC78

【注意】有两个例外

  1. sizeof(数组名),sizeof 中单独放数组名,这里的数组名表示整个数组,计算的是整个数组的大小,单位是字节
  2.  & 数组名,这里的数组名表示整个数组,取出的是整个数组的地址(整个数组的地址和数组首元素的地址是有区别的)
#include <stdio.h>
int main()
{int arr[5] = { 1,2,3,4,5 };printf("%p\n", arr);printf("%p\n", &arr);return 0;
}
//输出
//000000CC3238FA38
//000000CC3238FA38
//可以看到 &arr 打印的也是首元素地址

2 数组名 与 &数组名 的区别

#include <stdio.h>
int main()
{int arr[5] = { 1,2,3,4,5 };printf("%p\n", arr);printf("%p\n", arr + 1);printf("===================\n");printf("%p\n", &arr);printf("%p\n", &arr + 1);return 0;
}
//输出
//0000006E731EF618
//0000006E731EF61C
//===================
//0000006E731EF618
//0000006E731EF62C//注意:地址是十六进制数,相减后要转换成十进制数才是相差字节数
//例子:2C-18 = 14;  转十进制:1*16^1 + 4*16^0 = 20

(1)arr 和 arr+1 相差4个字节,是因为 arr 是首元素的地址,+1就是跳过一个元素。

(2)但是 &arr 和 &arr+1 相差20个字节,这就是因为&arr是数组的地址,+1 操作是跳过整个数组的。

其实跟指针一样,指针规定类型就是为了确定一步走多大,这里也是一样,不明白这句话可以看C 认识指针-CSDN博客 的指针+-整数;


二、使用数组访问指针

#include <stdio.h>
int main()
{int arr[5] = { 0 };int* p = arr;for (int i = 0; i < 5; i++)	//输入{scanf("%d", p + i);	//等同于 &arr[i] 或者 arr+i}for (int i = 0; i < 5; i++)	//输出{printf("%d ", *(p + i));	//等同于 arr[i] 或者 p[i]}return 0;
}
//输入 1 2 3 4 5
//输出 1 2 3 4 5

可以看到 p[i] 等同于 *(p + i), 可以正常打印;同理 arr[i] 等价于 *(arr+i)。

【原因】

数组元素的访问在编译器处理的时候,都是转换首元素的地址+偏移量求出元素的地址,然后解引用来访问的。


三、一维数组传参的本质

#include <stdio.h>
void test(int arr[])
{int sz2 = sizeof(arr) / sizeof(arr[0]);printf("sz2 = %d", sz2);
}int main()
{int arr[5] = { 1,2,3,4,5 };int sz1 = sizeof(arr) / sizeof(arr[0]);printf("sz1 = %d\n", sz1);test(arr);return 0;
}
//输出
//sz1 = 5
//sz2 = 2

我们发现在 test函数内部 是没有正确获得数组的元素个数。

因为 数组名是数组首元素的地址;那么在数组传参的时候,传递的是数组名,也就是说本质上数组传参传递的是数组首元素的地址。

所以函数形参的部分理论上应该使用指针变量来接收首元素的地址。在test函数内部的 sizeof(arr) 计算的是一个地址的大小(单位字节)而不是数组的大小(单位字节)。

【总结】

一维数组传参,形参的部分可以写成数组的形式,也可以写成指针的形式。


四、二级指针

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

#include <stdio.h>
int main()
{int a = 10;int* p = &a;int** pp = &p;int b = 20;*pp = &b;	//将 p 存放的地址改为 &bprintf("%d\n", **pp);	return 0;
}
//输出
//20

五、指针数组


六、指针数组模拟二维数组 

#include <stdio.h>
int main()
{int arr1[5] = { 1,2,3,4,5 };int arr2[5] = { 2,3,4,5,6 };int arr3[5] = { 3,4,5,6,7 };//数组名是数组⾸元素的地址,类型是int*的,就可以存放在parr数组中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)//1、*(parr + i) 等同于parr[i],找到 parr数组中第i个元素//2、假如 i = 0,那就是 *(arr1 + j),不就是前面讲的,相当于arr1[j]//3、合在一起就是parr[i][j]}printf("\n");	//打印完一行换行}return 0;
}
//输出
//1 2 3 4 5
//2 3 4 5 6
//3 4 5 6 7

【注意】

上述的代码是模拟出二维数组的效果,实际上并非完全是二维数组,因为每一行并非是连续的,而二维数组在内存中的存放是连续的。


完 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/834610.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

为什么要使用大模型

随着OpenAI引领的超大模型风潮&#xff0c;大模型的发展日新月异&#xff0c;如同雨后春笋般茁壮成长。在现今的科技舞台上&#xff0c;每周&#xff0c;甚至每一天&#xff0c;我们都能见证到一个全新模型的开源&#xff0c;这些模型的创新性和实用性不断超越前作&#xff0c;…

leetcode 1235

leetcode 1235 代码 class Solution { public:int jobScheduling(vector<int>& startTime, vector<int>& endTime, vector<int>& profit) {int n startTime.size();vector<vector<int>> jobs(n);for(int i0; i<n; i){jobs[i] …

Kotlin基础知识总结(三万字超详细)

1、条件语句 &#xff08;1&#xff09;if条件 if条件表达式&#xff0c;每一个分支最后一条语句就是该分支的返回值。适用于每个分支返回值类型一致这种情况。 fun getDegree(score: Int): String{val result: String if(score 100){"非常优秀"}else if(score …

Vue从入门到实战Day03

一、生命周期 1. 生命周期四个阶段 思考&#xff1a; ①什么时候可以发送初始化渲染请求&#xff1f; 答&#xff1a;越早越好&#xff0c;在创建阶段后 ②什么时候可以开始操作DOM&#xff1f; 答&#xff1a;至少DOM得渲染出来&#xff0c;在挂载阶段结束后。 Vue生命周…

SpringBoot+logback实现日志记录写入文件

前言 在实际的开发过程中&#xff0c;日志记录有着极其重要的作用&#xff0c;它帮助我们实现更高效的故障排查与调试、更及时的监控和性能优化、更全面的业务分析与决策支持…那么我们如何在SpringBoot项目中实现日志的个性化定制&#xff0c;以满足其他特殊需求呢&#xff1f…

987: 输出用先序遍历创建的二叉树是否为完全二叉树的判定结果

解法&#xff1a; 一棵二叉树是完全二叉树的条件是&#xff1a; 对于任意一个结点&#xff0c;如果它有右子树而没有左子树&#xff0c;则这棵树不是完全二叉树。 如果一个结点有左子树但是没有右子树&#xff0c;则这个结点之后的所有结点都必须是叶子结点。 如果满足以上条…

机器学习(三) ----------线性回归算法(梯度下降+正则化)

目录 1 定义 2 损失函数&#xff08;回归&#xff09; 2.1 最小二乘函数&#xff08;Least Squares Function&#xff09; 2.2 均方误差&#xff08;Mean Squared Error, MSE&#xff09; 2.3 均方根误差&#xff08;Root Mean Squared Error, RMSE&#xff09; 2.4 平均绝…

PC端网页特效异读

pc网页特效 一、三大系列1.元素偏移量&#xff08;offset系列&#xff09;&#xff08;1&#xff09;一些属性&#xff08;2).offset和style的区别(3).一些例子 2.元素可视区(client系列&#xff09;(1).一些属性(2).flexible.js源码分析 3.scroll系列(4).三大系列小结 其他&am…

libcity笔记:参数设置与参数优先级

1 参数优先级 高优先级的参数会覆盖低优先级的同名参数 Libcity中的优先级顺序维&#xff1a; 命令行参数&#xff08;命令行python run_model.py时导入的&#xff09; > 用户定义配置文件&#xff08;命令行python run_model.py时由config_file导入的&#xff09; >…

QT--4

QT 使用定时器完成闹钟 #include "widget.h" #include "ui_widget.h"void Widget::timestart() {timer.start(1000); }void Widget::timeend() {timer.stop(); }Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(t…

jsp 实验16 MVC 表白墙

源代码以及执行结果截图&#xff1a; ExpressWish_Bean.java package web; import java.util.HashMap; import java.util.ArrayList; import java.util.Iterator; public class ExpressWish_Bean { public HashMap<String,ExpressWish> wishList; ArrayList&…

图片公式识别@文档公式识别@表格识别@在线和离线OCR工具

文章目录 abstract普通文字识别本地软件识别公式扩展插件下载小结 在线识别网站/API&#x1f47a;Quicker整合(推荐)可视化编辑和识别公式其他多模态大模型识别图片中的公式排版 开源模型 abstract 本文介绍免费图片文本识别(OCR)工具,包括普通文字识别,公式识别,甚至是手写公…

2024面试自动化测试面试题【含答案】

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

每日Attention学习5——Multi-Scale Channel Attention Module

模块出处 [link] [code] [WACV 21] Attentional Feature Fusion 模块名称 Multi-Scale Channel Attention Module (MS-CAM) 模块作用 通道注意力 模块结构 模块代码 import torch import torch.nn as nnclass MS_CAM(nn.Module):def __init__(self, channels64, r4):super(…

Redis 的数据库管理

Redis 提供了⼏个⾯向 Redis 数据库的操作&#xff0c;分别是 dbsize、select、flushdb、flushall 命令&#xff0c; 我将介绍这些常见的命令。 切换数据库 select dbIndex许多关系型数据库&#xff0c;例如 MySQL ⽀持在⼀个实例下有多个数据库存在的&#xff0c;MySQL 可以…

SQL优化详解

目录 插入数据 insert的优化&#xff08;少量数据&#xff09; 批量插入 手动事务提交 主键顺序插入 插入大量数据 主键优化 数据组织方式&#xff1a; 页分裂&#xff1a; 主键顺序插入的方式&#xff1a; 主键乱序插入&#xff1a; 页合并&#xff1a; 主键设计…

模板引擎Freemarker

什么是模板引擎 根据前边的数据模型分析&#xff0c;课程预览就是把课程的相关信息进行整合&#xff0c;在课程预览界面进行展示&#xff0c;课程预览界面与课程发布的课程详情界面一致。 项目采用模板引擎技术实现课程预览界面。什么是模板引擎&#xff1f; 早期我们采用的…

【有趣的透镜】1.透镜初相识

1.透镜的外形和材料 (1)透镜由玻璃或者塑料制成&#xff1b; (2)透镜一般为圆型&#xff0c;其单面或双面为球面&#xff1b; 2.透镜的类型和折射 (1)球面外凸为凸透镜(聚光)&#xff0c;球面内凹为凹透镜(散光)&#xff1b; (2)透镜是基于光的折射&#xff0c;只要光从一…

Linux的基本指令(下)

各位大佬好 &#xff0c;这里是阿川的博客 &#xff0c; 祝您变得更强 个人主页&#xff1a;在线OJ的阿川 大佬的支持和鼓励&#xff0c;将是我成长路上最大的动力 阿川水平有限&#xff0c;如有错误&#xff0c;欢迎大佬指正 这篇博客续博主的上篇博客Linux基本指令。 07 …

MATLAB 三维空间中在两点之间等间隔插入多个点 (67)

MATLAB 三维空间中在两点之间等间隔插入多个点 (67) 一、算法介绍二、算法实现1.代码2.结果一、算法介绍 用于加密直线点云,具体为根据给定的直线端点,沿着该直线方向,插入多个点,从而加密。具体方法和效果如下所示: 二、算法实现 1.代码 代码如下(示例): % 定…