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

批量组织相同数据类型的基础数据结构——数组

批量组织相同数据类型——数组

  • C语言将数组看作派生类型(建立在其他类型的基础上)
  • []:变地址运算符,表示将指针移动多少个存储单元。如a[n]=a[0]+n*sizeof(a[0]);
  • 数组的索引,即为下标(变地址运算符中的偏移量)。数组索引范围: [ 0 , 数组大小 − 1 ] [0,数组大小-1] [0,数组大小1]。数组越界(索引超出范围,索引为负数等)是未定义行为(访问了未经申请的内存)。
  • C99之后增加了变长数组(VLA),允许用变量表示数组的维度(包括用const修饰符限定的变量)。注意,VLA并非在运行时可以自动改变数组大小。VLA必须为自动(auto)存储类别,不能为static或extern,且不能在声明时进行初始化。
  • 数组的初始化分为完全初始化与不完全初始化。对于非字符数组类型,初始化数组采用序列表的方式(即为{}的形式),序列表仅允许在初始化时使用。对于不完全初始化,编译器会将未初始化的部分设为0。如果在块作用域中没有初始化数组且为自动数组(auto),会被填充随机值,一般将随机值视为垃圾数据。
  • 指定初始化器:可以在初始化列表中指定待初始化的元素。例:int arr[6]={[5]=0};指定初始化器的用法可以与普通初始化的方法混用。例:int a[6]={1,[3]=5,6,7};中,由于中间使用逗号运算符进行分隔,故执行顺序为从左到右依次进行,a[0]=1,a[3]=5,a[4]=6,a[5]=7;其余为0。若对同一元素出现了多次修改,则以最后面的作为最终结果(逗号运算符特性,后面的会覆盖前面的)。这种下标继承方式类似于枚举中的用法。
    注:指定初始化器的方式进行初始化为C99的扩展,标准C++不支持这种写法,具体实现取决于C++编译器(g++不允许,clang++允许)。
  • 求数组长度:(sizeof(数组名)/sizeof(数组名[0]))(再次注意:sizeof是标识符而非函数)
  • 常量数组:加上const修饰符的数组,一旦创建之后,数组将为只读,内容不可被修改。
  • 不允许直接将一个数组通过赋值表达式给其他数组。
  • 数组名:即为整个数组的地址,同时也是数组中首元素的地址(即数组的基址)。
  • 基址是指用于定位数据结构中元素位置的地址。它通常指向数据结构的起始位置或者某个特定元素的位置。基址通常与偏移量结合使用,通过基址加上偏移量来计算访问数据结构中的特定元素的内存地址。

    在数组中,基址指的是数组的起始地址,即数组的首元素的地址。数组名在大多数情况下可以被视为数组的基址,通过数组名可以访问数组中的元素,时间复杂度为 O ( 1 ) O(1) O(1)。因此,数组中变地址运算符可视为数组的偏移量。

    在函数调用中,基址指的是当前函数栈帧的基址,也就是栈帧中局部变量和参数的起始地址。基址指针在函数调用过程中用于帮助定位局部变量和参数。

    总的来说,基址是用于定位数据结构中元素位置的地址,它是访问数据结构中元素的起点。

  • 数组是一种顺序表,在内存中存储是连续的

多维数组

以最简单的多维数组——二维数组举例:

C语言遵循高维度优先原则,在二维数组中体现为行优先原则。二维数组的初始化,为避免混淆,一般采用嵌套序列表的方式进行(但并不绝对)。

int a[6][4];//定义了一个6行4列的二维数组

二维数组是若干个一位数组的数组,二维数组的每一个元素都是一维数组。对于上述二维数组a,其本身是一个有6个元素的一维数组(a[3])称为主数组。主数组中的每个元素是包含4个元素的一维数组。

注意:数组是顺序表,在内存中始终是顺序存储的,行和列只是为了方便理解而创造出来的,在内存中存储并不涉及行和列的概念。

从指针角度看二维数组:

  • 数组名a是整个主数组a的地址,也是主数组中首元素a[0]的地址,a[0]是大小4个int的数组,因此a是占有4个int大小对象的地址。
  • a[0]元素本身是一个数组,因此a[0]是a[0]中首元素a[0][0]的地址,因此a[0]是占用1个Int大小对象的地址。
  • 一句话总结:a=&a[0],a[0]=&a[0][0];*a=*(&a[0])=a[0]=&a[0][0],**a=*a[0]=*(&a[0][0])=a[0][0]
  • 以上地址的地址(二级地址)、指针的指针(二级指针),是双重间接

例:

a+1//a=&a[0],a[0]是4个int大小的数组,因此a+1为+4个int大小,即为行指针下移,变为a[1]
a[0]+1//a[0]=&a[0][0],列指针下移,变为a[0][1]
(a+1)[2]//a=&a[0],行指针下移1个存储单元,变为a[1],之后通过变地址运算符行指针再下移2行,变为a[3]
(a[0]+1)[2]//a[0]=&a[0][0],列指针下移1个存储单元,变为a[0][1],之后通过变地址运算符列指针再右移2个存储单元。再次注意:数组是顺序表,在内存中存储是连续的,因此可跨行移动
(a+1)[0][2]//a=&a[0],行指针下移1个存储单元变为a[1],之后通过变地址运算符转换为列状态,列指针再下移2个存储单元

从存储单元角度理解,会发现容易很多。

  • 二维数组在函数定义中做函数形参时,行可以缺省,但列不能缺省。即使行未缺省,编译器也会自动忽略该值。对于多维数组来说,在函数定义中做形参时,只能省略最左侧方括号中的值。(因为最左侧方括号表明其为一个指针)。
  • VLA的二维数组在函数声明时若要省略维度形参,必须用*来代替省略的维度。在函数定义时则只能缺省最左侧的维度形参,其余维度形参在函数形参表中必须比数组先进行声明。(注意形参永远只能被看作是声明而非定义,因为形参只发生在函数调用时而非函数定义时)

指针数组

注意优先级[]>*

int *p[2];//定义了大小为2的数组,每个元素都是int*(int型指针)
//其实应该相当于:
int* p[2];

数组指针

注意优先级[]>*

int (*p)[2];//定义了一个可以指向含有2个int型元素的一维数组的指针

在二维数组中应用数组指针则相当于行指针。

以上内容可以用指针函数和函数指针数组理解

相关文章:

  • Lua Global环境
  • 掌握rm命令:Linux文件删除的艺术与安全指南
  • 常见的Web前端开发框架推荐
  • 8868体育助力意甲国际米兰俱乐部 国米锁定意甲冠军
  • Leetcode - 周赛384
  • C++ //练习 6.11 编写并验证你自己的reset函数,使其作用于引用类型的参数。
  • 论文阅读:GamutMLP A Lightweight MLP for Color Loss Recovery
  • 【读书笔记】ICS设备及应用攻击(一)
  • 中断系统(单片机)
  • 杨中科 ASP.NET DI综合案例
  • OpenAI Sora 初体验
  • Android Compose 一个音视频APP——Magic Music Player
  • Arrays工具类的常见方法总结
  • 高校疫情防控系统的全栈开发实战
  • Day37 贪心算法part06
  • hexo+github搭建个人博客
  • 【MySQL经典案例分析】 Waiting for table metadata lock
  • el-input获取焦点 input输入框为空时高亮 el-input值非法时
  • es6要点
  • Facebook AccountKit 接入的坑点
  • JavaScript实现分页效果
  • Java教程_软件开发基础
  • mockjs让前端开发独立于后端
  • mysql_config not found
  • nginx(二):进阶配置介绍--rewrite用法,压缩,https虚拟主机等
  • node学习系列之简单文件上传
  • PHP的类修饰符与访问修饰符
  • Spark学习笔记之相关记录
  • v-if和v-for连用出现的问题
  • vue+element后台管理系统,从后端获取路由表,并正常渲染
  • vue学习系列(二)vue-cli
  • vue自定义指令实现v-tap插件
  • webpack4 一点通
  • 大主子表关联的性能优化方法
  • 构建工具 - 收藏集 - 掘金
  • 前端每日实战:70# 视频演示如何用纯 CSS 创作一只徘徊的果冻怪兽
  • 如何实现 font-size 的响应式
  • 删除表内多余的重复数据
  • 微信端页面使用-webkit-box和绝对定位时,元素上移的问题
  • # Java NIO(一)FileChannel
  • #鸿蒙生态创新中心#揭幕仪式在深圳湾科技生态园举行
  • #我与Java虚拟机的故事#连载08:书读百遍其义自见
  • (Demo分享)利用原生JavaScript-随机数-实现做一个烟花案例
  • (二十五)admin-boot项目之集成消息队列Rabbitmq
  • (附源码)springboot 基于HTML5的个人网页的网站设计与实现 毕业设计 031623
  • (六)c52学习之旅-独立按键
  • (三)Hyperledger Fabric 1.1安装部署-chaincode测试
  • (十七)Flask之大型项目目录结构示例【二扣蓝图】
  • (一)ClickHouse 中的 `MaterializedMySQL` 数据库引擎的使用方法、设置、特性和限制。
  • (转)Sql Server 保留几位小数的两种做法
  • (转)清华学霸演讲稿:永远不要说你已经尽力了
  • (转)详解PHP处理密码的几种方式
  • .NET C# 使用 SetWindowsHookEx 监听鼠标或键盘消息以及此方法的坑
  • .NET Core 通过 Ef Core 操作 Mysql
  • .NET Core 网络数据采集 -- 使用AngleSharp做html解析