MQL5语言帮助文件人话版(十五)数据类型之数组

| 发表于 7 小时前 | 显示全部楼层 |复制链接
最后由 麻爪 于 2026-9-8 13:05 编辑

第十六章 数组

一、什么是数组?

数组是存放一批相同数据类型元素的容器;下标全部从0开始。
数组一共两大分类:静态数组、动态数组;又支持多维(一维、二维、三维、四维)

二、数组命名

前面见过的所有数据类型,都有个关键字作为类型名称,比如int、struct、class等等,但数组没有相关的类型名称,数组以方括号[ ]为特征,具体格式是 数据类型+自定义数组名称+[ ],方括号[ ]里面可以有个表述成员个数的非负整数,有这个数字即为静态数组,没这个数即为动态数组。比如:

double arr[10];
// double,数组内部成员的数据类型,可以是前面说的大多数数据类型,但不能是类class,可以放类的指针。所有成员必须同类型。
// arr,自定义的数组名称,可以按照标识符的命名规则,随便起自己想要的名字,不能与语言关键字相同。
//方括号[ ],是数组的标志。里面是数字代表成员数量,可以为0但没有业务意义,一般为正整数。不能写负数或者多个数
//如果想让数组的成员数量不固定,可以不写数字,方括号[ ]空着,表示动态数组。
//不能命名一个变量当数组成员数量,比如 int num = 10,double arr[num];,这样会报错。

三、静态数组:

(一)静态数组特点:
(1)编译阶段就分配全部内存,你设定多少个成员就是多少个成员,且运行期间也不能改变,不能由数组函数ArrayResize()修改成员个数和类型。
(2)全局静态数组:元素默认全部初始化为 0;
(3)函数内部局部静态数组:不初始化就是随机垃圾值。
(4)局部大静态数组容易栈溢出,不要在函数内写double buf[50000]。
(5)结构体struct内部只能放静态数组,不能放动态数组。
(6)适合固定长度数据、DLL 结构体;不适合处理K 线数据。
(二)静态数组的初始化:
(1)所谓初始化:定义数组的同时给值(写在同一行),相当于初次赋值。由此也可以理解一下编程中的初始化概念,大同小异。就是给所有的参数一个初始值,避免有意外存留的垃圾数值影响系统运行。
(2)全局静态数组:自动全部初始化为 0;函数内局部静态数组:不手动设置初始化,内存是随机垃圾值。
(3)完整初始化,定义同时使用大括号 { }把全部元素写满:double arr[5] = {1.1, 2.2, 3.3, 4.4, 5.5}; ,五个元素,给出五个对应值。
(4)部分初始化,定义时,只写前面一部分,剩下自动补 :double arr[5] = {1.1,2.2}; ,只定义了两个数,系统会自动把剩余的三个数默认为0,但只能在定义同时赋值的时候,可以使用这种省略写法。在后面所说的批量赋值时,如果省略一部分,那这部分数值还会是之前储存的垃圾数字。
(5)空大括号初始化,所有成员全部置 0:double arr[5] = {}; ,相当于所有 5 个元素全部等于 0,这是局部静态数组快速清零的便捷写法。
(6)省略方括号里面的数字, 编译器根据大括号里面值的个数,自动推算数组长度:double arr[] = {1,2,3,4}; ,等价于 double arr[4]={1,2,3,4}; ,但这还是静态数组,而不是动态数组,动态数组没有等于号以及大括号和里面的数字。
(三)静态数组的聚合初始化
(1)聚合初始化:当结构体是聚合类型(没有自定义构造函数、没有 private 成员),可以在定义结构体变量的那一行,用一对大括号 { },一次性给结构体里面全部成员赋值,这个语法就叫聚合初始化(这讲的是结构体给自己的成员初始化,不是针对数组)。
(2)当结构体里面包含静态数组,数组本身不能脱离结构体单独写大括号初始化;要嵌套进结构体的聚合大括号里面完成(相当于数组要在结构体的大括号里面再写自己的大括号)。
(3)聚合初始化只允许写在变量定义那一行。结构体变量已经创建完成之后,不能再用大括号批量赋值,只能循环逐个赋值。
(4)示例:
struct ZB_Data //定义一个结构体
{              
int id;        //结构体成员1,一个int类型的数据
double buf[4]; //结构体成员2,静态数组,自身有四个成员   
bool valid;    //结构体成员3,一个bool类型的数据
};


ZB_Data d =   //用自定义ZB_Data结构体,定义一个结构体数据d,并进行初次赋值,也就是“聚合初始化”
{
    100,               // 结构体成员1,赋值100,相当于id=100
    {1.1,2.2,3.3,4.4}, // 结构体成员2,buf[4]静态数组,给四个成员赋值,要有内层大括号
    true               // 结构体成员3赋值,valid = true
};
(四)静态数组的批量赋值:
(1)所谓批量赋值:数组已经定义完毕,后续代码再给一批元素赋值,相当于代码正常运行过程中的赋值,系统运行完毕,很可能会有残留数值存在数组之中,所以再次运行需要进行初始化。
(2)数组定义完成之后批量赋值手段:for 循环逐个赋值、ArrayCopy 数组复制。后面到相关函数、语句时再详细讲解。

四、动态数组

(1)动态数组定义时方括号为空 double arr[];,编译期不指定大小,运行时才分配、修改元素个数。
(2)动态数组天生自带原生动态数组对象(管理面板,底层语言规则,不用管它),这个面板是它与生俱来的。允许ArraySize()、ArrayResize()、ArraySetAsSeries() 等函数定义和修改它。
(3)动态数组定义完之后,其元素数量为 0,没有分配数据内存。必须调用 ArrayResize() 才会开辟真实存放数据的内存。
(4)动态数组的各种操作需要通过数组相关函数来实现,等我们研究到相关函数时再详细介绍。

五、数组下标
(1)数组的下标也叫索引,符号就是方括号 [下标数值],用来定位数组里面某一个具体元素,本质上是就是数组成员的编号。
(2)无论静态数组、动态数组,下标全部从 0 开始计数,不从 1 开始。所以有5个成员的数组,其成员下标最大只是4,而不是5。最大下标 = 元素总个数 减去 1。
(3)数组成员的下标是非负整数。不能是:
①负数下标:arr[-1],越界错误
②小数:arr[2.5],编译报错,下标必须整数
③bool、datetime 不能当下标
(4)当成员只有5个,你却写出下标5时,叫做越界访问。编译器不会检查下标是否越界!编译可以正常通过,运行时才出问题。发生越界访问时,系统多数情况下都可以正常运行,但它拿到的数据可能是其他数据或着垃圾值,从而让你的EA表现出莫名其妙的错误。

六、数组的维度
MQL5语言最多支持4维数组。所谓维度,就是数组下标需要写几个 [ ]。
(1)一维数组:arr →1 个下标,代表只有一组索引,相当于一长条数据;
(2)二维数组:arr[j] →2 个下标,代表有二组索引,相当于有行、有列的表格类数据;
(3)三维数组:arr[j][k] →3 个下标,代表有三组数据,相当于在行和列上面增加了层的概念;
(4)四维数组:arr[j][k][l],代表有四组数据,相当于一排立方体数据,每个立方体里面都有一套三维数组。
通常我们写EA,用一维数组就够用了,二维极少用,非常复杂的策略可能会用到三维、思维数组。

七、数组相关常用内置函数简介
(1)ArrayResize():动态数组分配 / 修改大小
(2)ArraySize():获取数组元素数量
(3)ArrayCopy():数组复制
(4)ArrayClear():清空数组,大小置 0
(5)ArraySetAsSeries():极其重要!K 线数组反转索引,[0]代表最新 K 线。只对动态数组有效。
最近访问 头像模式
举报

评论 使用道具

发新帖
EA交易
您需要登录后才可以评论 登录 | 立即注册