【C语言】指针与数组的潜在联系

目录

前言

改变固有数组的平面思维

注意:

数组操作与指针等价

指针数组

数组指针

笔试加深理解:

        解析:


前言

        《C Traps and Pitfalls》(C语言缺陷与陷阱)中有一句著名的见解:

        “在C语言中,指针与数组这两个概念之间的联系时如此密不可分,以至于如果不能理解一个概念,就无法彻底理解另一个概念。”


改变固有数组的平面思维

        在本质上,C语言只有一维数组,只是数组的元素可以是任意类型的对象,当然也可以是一个数组!于是,这样就产生了高维数组!


        对于:

​int arr[6][4];

        在上图中,arr是一个一维数组,内部含有六个元素;每个元素(arr[0],arr[1]......arr[5])的类型是一个数组类型,假设这个数组(arr[0],arr[1]......arr[5])中的元素   arr[i][j]    是整形,那么这个数组(arr[0],arr[1]......arr[5])的类型是  int (*)[4]  ;

        换句话说:

        这个语句声明的arr是一个数组,该数组拥有6个数组类型的数据,其中每个元素都是一个拥有4个整形元素的数组。(而不是一个拥有4个数组类型的数组,其中每一个元素是一个拥有6个整形元素的数组)

        其实,对于数组arr,它就是一个主串(主数组)上伸出了许多子串(子数组);类似于河流的主流外有许多支流:

        它可以是随意分布的,我们平时为了清晰,我们一般画图将二维数组画成二维棋盘形状。

        我们实际上可以将数组画成任意分布,只要满足C标准: 

 (二维平面不好演示,请自行脑补拖把头每根布的分布)

        其实,我们也可以从数组arr的创建格式上看出端倪:

int arr[6][4];//请重新审视这段代码,以便于加深对他的理解

        这段代码可以翻译为:

        创建一个名字为arr的数组,内部元素为6个  int (*)[4]  类型的数组。其实就是从前到后对这段代码进行翻译。

注意:

         这样一边翻译一边理解的思想是十分重要的,如果不采取这样的思想,那么对于数组指针,指针数组,函数指针,函数指针数组 的理解和区分 将十分困难!

数组操作与指针等价

        对于一个数组,我们只能做两件事:

        确定该数组的大小  以及  获得指向该数组下标为0的元素的指针。

        对于其他有关数组的操作,其实本质上就是指针的操作。也就是说:任何一个数组下标的运算都等同于一个对应指针的运算,因此,指针操作与数组操作是可以相互转化的。

        数组可以看作是一组相邻的内存单元的集合,而指针则是一个指向内存地址的变量。由于数组实际上就是一段连续的内存空间,因此可以使用指针来访问数组中的元素。

        具体来说,可以将数组名看作是一个指向数组第一个元素的指针,即数组名本身就是一个地址。因此,使用指针变量来对数组进行操作就非常方便,如以下示例:

​
int arr[5] = {1, 2, 3, 4, 5};
int *p = arr;   // 将数组名赋值给指针
for (int i = 0; i < 5; i++) {printf("%d ", *(p + i));  // 使用指针来访问元素

指针数组

        C语言中的指针数组是指一个数组,其中的每一个元素都是一个指针。这样的数组可以用于存储多个指针,以便对它们进行操作。

        例如,一个指针数组可以用于存储不同类型的指针,如整型指针、字符型指针、结构体指针等:

int *ptrArray[10];     // 整型指针数组,包含10个元素
char *strArray[5];     // 字符型指针数组,包含5个元素
struct person *personArray[100];     // 结构体指针数组,包含100个元素

        可以通过下标来访问数组中的元素,并对其进行操作:

int a = 10, b = 20, c = 30;
int* ptrArray[3] = { &a, &b, &c };for (int i = 0; i < 3; i++) {printf("%d ", *ptrArray[i]);    // 指针数组中的每个元素都是整型指针,需要使用 * 解引用
}// 输出结果为:10 20 30

数组指针

        在C语言中:

        整形指针变量: int * pint; 存放的是整形变量的地址,能够指向整形数据的指针。
        浮点型指针变量: float * pf; 存放浮点型变量的地址,能够指向浮点型数据的指针。
        那数组指针变量应该是:存放的应该是数组的地址,能够指向数组的指针变量。


        数组指针本质上是一个指针变量,但它可以指向一个数组,从而允许对数组的操作。

由于结合性的问题,数组指针的写法与指针数组的大不相同:

int *p1[10];
int (*p2)[10];

解释:

        1.是前文介绍的指针数组;

        2.p先和*结合,说明p是⼀个指针变量变量,然后指着指向的是⼀个⼤⼩为10个整型的数组。所以
        p是⼀个指针,指向⼀个数组


这里要注意:[ ]的优先级要高于*号的,所以必须加上()来保证p先和*结合。

初始化:

int arr[10] = {0};
int(*p)[10] = &arr;

应用数组的地址初始化数组指针。并且,数组指针p与arr的类型是相同的。

这照应了本文的第一部分,数组指针是高维数组的基础。


        现在有了一定的知识基础,不妨做一些题目检测一下: 

笔试加深理解:

题目1:

​
#include <stdio.h>
int main()
{
int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };//#int *ptr1 = (int *)(&aa + 1);//*int *ptr2 = (int *)(*(aa + 1));//¥printf( "%d,%d", *(ptr1 - 1), *(ptr2 - 1));//&
return 0;
}​

        解析:

        #行:

        对数组aa初始化,aa两行五列;

        *行:

        创建整型指针ptr1, 取出aa的地址 +1 后强制类型转化为int*,放入ptr1;

        对数组的地址运算,实际上+1表示跳过整个数组。此时ptr1指向数组紧跟着的一个元素的地址。

        表达式的类型是int (*)[5],强制类型转化后是int*,刚好可以存入ptr1中。

        ¥行:

        aa+1 中的aa表示数组首元素的地址,是  int aa[0] 的地址, 这一点很重要——这第三次照应了数组aa是一维数组,每一个元素也是一个数组,那么aa中的每一个元素都是数组类型,而不是aa中的元素类型是int型。

        aa + 1 表示指向第二行,存放的是第二行的地址,表示第二行的首元素地址。

        &行:打印*(ptr1-1),即数组最后一个元素;打印*(ptr2-1),即第二行前的一个元素。

结果:


完~

未经作者同意禁止转载 

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

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

相关文章

【华为数据之道学习笔记】1-2华为数字化转型与数据治理

传统企业通过制造先进的机器来提升生产效率&#xff0c;但是未来&#xff0c;如何结构性地提升服务和运营效率&#xff0c;如何用更低的成本获取更好的产品&#xff0c;成了时代性的问题。数字化转型归根结底就是要解决企业的两大问题&#xff1a;成本和效率&#xff0c;并围绕…

linux基础五:linux 系统(进程状态+进程优先级+调度和切换+环境变量)

linux 系统 一.进程状态&#xff1a;1.睡眠状态(sleep)&#xff1a;2.磁盘休眠状态(disk sleep)&#xff1a;3.停止状态(stoped --- T)&#xff1a;4.死亡状态&#xff1a;5.控制状态&#xff08;t&#xff09; 二.僵尸进程和孤儿进程&#xff1a;1.僵尸状态&#xff1a;2.孤儿…

天眼销:精准的企业名录

企业名录的重要性&#xff0c;对于销售而言都是极其重要的。本期为家人们分享如何正确挑选出优质的企业名录渠道&#xff0c;避免走一些弯弯坑坑。 为了有效利用企业名录进行客户开发&#xff0c;您需要关注信息的准确性、可提供的资源数量以及信息的时效性。能否根据您的需求…

山西电力市场日前价格预测【2023-12-05】

日前价格预测 预测说明&#xff1a; 如上图所示&#xff0c;预测明日&#xff08;2023-12-05&#xff09;山西电力市场全天平均日前电价为118.23元/MWh。其中&#xff0c;最高日前电价为305.71元/MWh&#xff0c;预计出现在00:15。最低日前电价为0.00元/MWh&#xff0c;预计出…

MyBatis学习笔记

MyBatis中文网&#xff1a;https://mybatis.net.cn/ 1 什么是 MyBatis&#xff1f; MyBatis 是一款优秀的持久层框架&#xff0c;它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。 MyBatis 可以通过简单的 XML 或…

实用篇 | 一文学会人工智能中API的Flask编写(内含模板)

在日常人工智能演示中&#xff0c;比较常用的api展示方式如flask,gradio等Web调用方式。在本文中&#xff0c;详细描述了在编写flask api中语法及语音文本图像模版案例等~ Flask是微型的Python Web框架&#xff0c;如果模型本身就是用python语言构建的&#xff0c;那么利用FLa…

YOLOv3 快速上手:Windows 10上的训练环境搭建

文章目录 前言一、前期准备二、基础环境准备1. 创建虚拟环境2. 打开Terminal3. 下载YOLOv3运行环境 三、PyCharm关联3.1 运行PyCharm3.2 关联Anaconda虚拟环境 四、运行环境检查1. 检查requirements.txt文件2. 安装依赖 五、运行代码5.1 运行检测代码5.2 运行训练代码 六、常见…

虹科干货 | 关于JSON数据库

来源&#xff1a;艾特保IT 虹科干货 | 关于JSON数据库 原文链接&#xff1a;https://mp.weixin.qq.com/s/NutCGWa32rOcEHrk3UDGcQ 欢迎关注虹科&#xff0c;为您提供最新资讯&#xff01; 如何理解JSON数据库&#xff1f;作为NoSQL数据库的一种类型&#xff0c;JSON数据库有哪…

罗技鼠标使用接收器和电脑重新配对

罗技鼠标使用接收器和电脑重新配对 文章目录 罗技鼠标使用接收器和电脑重新配对1\. 前言2\. 安装软件3\. 进行配对3.1. 取消之前的配对3.2. 重新配对3.3 配对完成 4\. 报错4.1. 重新配对时显示配对未成功 1. 前言 罗技的鼠标出厂的时候&#xff0c;默认的是将通道一设置为接收…

如何通过navicat连接SQL Server数据库

本文介绍如何通过Navicat 连接SQL Server数据库。如果想了解如何连接Oracle数据库&#xff0c;可以参考下边这篇文章。如何通过Navicat连接Oracle数据库https://sgknight.blog.csdn.net/article/details/132064235 1、新建SQL Server连接配置 打开Navicat软件&#xff0c;点击…

链表|2. 两数相加160. 相交链表 234. 回文链表

2. 两数相加 题目&#xff1a;给你两个非空的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照逆序的方式存储的&#xff0c;并且每个节点只能存储一位数字。 请你将两个数相加&#xff0c;并以相同形式返回一个表示和的链表。 你可以假设除了数字 0 之外&#xff0…

极简模式,助力宏观数据监控

随着UWA GOT Online采样的参数越来越多样化&#xff0c;为了提升开发者的使用体验&#xff0c;我们最新推出了三种预设数据采集方案&#xff1a;极简模式、CPU模式、内存模式。该更新旨在降低多数据采集对数据准确性的干扰&#xff0c;同时也为大家提供更精准且有针对性的数据指…

解决使用Flipper无法连接到苹果模拟器,却能连接到安卓

而且这些都是显示正常 可是打开Virtual device一看ios一直在加载中 然后我打开日志看了下&#xff0c;然后各种找配置&#xff0c;项目里边配置改了又改&#xff0c;最后发现是缺少了个插件 //1、 检查 idb 和 idb_companion 是否已经安装 brew tap facebook/fb brew install …

Chart 3 Adreno OpenCL 应用程序开发

文章目录 前言4.1 Android上进行OpenCL应用程序开发4.2 Adreno OpenCL SDK 和 Adreno OpenCL 机器学习 SDK4.3 调试工具和技巧 前言 本章主要介绍如何 debug Adreno OpenCL应用程序 4.1 Android上进行OpenCL应用程序开发 Adreno GPU 主要在 Android 操作系统和部分 Linux 系统…

二叉树刷题Leetcode

文章目录 104.二叉树的最大深度100.相同的树965.单值二叉树 104.二叉树的最大深度 int maxDepth(struct TreeNode* root) {if(rootNULL)return 0; int left1maxDepth(root->left); int right1maxDepth(root->right); return left>right?left:right; }处理二叉树最大深…

感觉到自己思想扭曲了

突然觉得自己思想有点扭曲。 ​起因是近期备婚&#xff0c;需要给男方家人买衣服。问男朋友妹妹衣服预算多少&#xff0c;说是500内&#xff0c;然后想想自己这个新娘子&#xff0c;那一身衣服绞尽脑汁凑满减不到300。再联想到装饰新房&#xff0c;新房买家具&#xff0c;为了省…

TikTok与社会责任:平台如何推动正能量?

近年来&#xff0c;TikTok作为一款备受欢迎的社交媒体平台&#xff0c;不仅令人们畅享创意短视频&#xff0c;更在推动社会正能量方面发挥了积极作用。 本文将深入探讨TikTok在社会责任方面的表现&#xff0c;探究其是如何通过不同的举措推动正向影响&#xff0c;引领社会向更…

23史上最全版---SQL注入详解

漏洞原因 一些概念&#xff1a; SQL&#xff1a;用于数据库中的标准数据查询语言。 web分为前端和后端&#xff0c;前端负责进行展示&#xff0c;后端负责处理来自前端的请求并提供前端展示的资源。 而数据库就是存储资源的地方。 而服务器获取数据的方法就是使用SQL语句进…

【开源】基于Vue+SpringBoot的数据可视化的智慧河南大屏

项目编号&#xff1a; S 059 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S059&#xff0c;文末获取源码。} 项目编号&#xff1a;S059&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块三、系统展示四、核心代码4.1 数据模块 …

AntV和AntD之间的区别与联系

前言&#xff1a;最近在调研前端的一些框架&#xff0c;技术栈主要是用react&#xff0c;所以找到了2个十分相似解决方案&#xff0c;拿来对比一下&#xff08;antd和antv都是基于react&#xff09; antd对比antv antd antv 解决方案企业级 UI 设计语言数据可视化解决方案提供…