从基础到中级:FOR 语句·进阶篇
📘

从基础到中级:FOR 语句·进阶篇

第 2/2 篇

for循环初值放错位置的打印差异

这段脚本演示了同一个计数循环,仅因初始化表达式写法不同,输出序列就会出现明显偏移。第一段代码在 for 里用空初始化,循环体前先 Print 了一次 info=10,随后从 10 递减到 1 打印,共 10 次循环打印。 第二段把 info=info-1 写进 for 的初始化段,进入循环时 info 已变成 9,最终只从 9 打印到 1,少打了一个数。两种写法在 MT5 里跑出来的日志行数差 1 行,肉眼能直接核对。 外汇与贵金属 EA 调试时,这种边界差最容易让仓位计数或重試次数偏离预期,属于高风险环境下的隐性 bug。开 MT5 新建脚本粘下面代码,切到 Experts 标签就能看前后两段输出对比。

MQL5 / C++
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#class="kw">property copyright "Daniel Jose"
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnStart(class="type">void)
{
   class="type">char info = class="num">10;

   Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");

   for( ; info; info = info - class="num">1)
      Print(__FUNCTION__, " : ", info);

   Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
}
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#class="kw">property copyright "Daniel Jose"
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnStart(class="type">void)
{
   class="type">char info = class="num">10;

   Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");

   for(info = info - class="num">1; info; info = info - class="num">1)
      Print(__FUNCTION__, " : ", info);

   Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
}
class=class="str">"cmt">//+------------------------------------------------------------------+

「拆开 FOR 循环的控制流」

MQL5 里 FOR 循环的执行顺序常被误读。它分三段:表达式01只在进入循环前跑一次,用来初始化;表达式02每次迭代前做条件判断;表达式03在循环体跑完后再执行,专门负责更新计数变量。代码02和03里表达式01留空,编译器直接跳过,不声明也不初始化,此时只能靠全局变量或前置赋值撑住逻辑。 流程图里画的是 IF 来做条件判断,但严格说这里本质就是 WHILE:表达式02为假就终止,为真才进循环体。把表达式01和03都置空时(如代码02),FOR 退化成和 WHILE 等价的形态,这也是为什么原文说图里的 IF 该写成 WHILE。 表达式03的价值在安全性——它强制把计数变量的更新绑在循环结构里,避免像手写 WHILE 那样漏写 i++ 导致死循环。代码03中 info 从初值经循环递减,终端打印的却是 info+1,最终 info 落为 0,打印序列和直观预期不同,这点在 MT5 里跑一遍就能验证。外汇与贵金属行情高波动,回测此类逻辑须用真实 tick 数据,结论仅具概率倾向。

◍ FOR 循环头空白反而成了无限循环

在 MQL5 里,FOR 循环的标准写法是 for(初始化; 条件; 迭代),三处表达式通常至少留个终止条件。但语法上允许把中间的条件表达式完全留空,写成 for(;;),编译器会把它当作无限循环处理。 下面这段代码(对应原文代码 06)就是用空 FOR 循环实现和前面 do-while 一样的 ESC 退出逻辑。循环头第 8 行 for(;;) 没有任何终止条件,退出完全靠第 14 行在循环体内判断 ESC 键后 break。 [CODE] //+------------------------------------------------------------------+ #property copyright "Daniel Jose" //+------------------------------------------------------------------+ void OnStart(void) { char info = 10; for (; ; ) { if (((info / 5) * 5) == info) Print("Press ESC to finish counting..."); info = info - 1; Sleep(200); Print(__FUNCTION__, " : ", info); if (TerminalInfoInteger(TERMINAL_KEYSTATE_ESCAPE)) break; } Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway..."); } //+------------------------------------------------------------------+ [/CODE] 逐行拆解:第 6 行 char info = 10 设计数器从 10 往下走;第 8 行 for (; ; ) 是空头无限循环;第 10 行每逢 info 为 5 的倍数就提示按 ESC;第 11 行每次减 1;第 12 行 Sleep(200) 让出 200 毫秒避免卡死终端;第 13 行打印当前值;第 14 行检测 ESC 状态,为真则 break 跳出;第 17 行确认跳出后后续代码照常执行。 实战里这种写法极少用——原作者做了多年程序员也只手动写过几次。但你在读别人 EA 源码时若撞见 for(;;),别当成笔误或死机前兆,它只是把终止条件挪进了循环体。外汇与贵金属 EA 调试中,这类空循环若漏写 break 条件,可能让 MT5 终端陷入不受控挂起,属高风险操作,上机前务必确认退出路径。

MQL5 / C++
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#class="kw">property copyright "Daniel Jose"
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnStart(class="type">void)
{
   class="type">char info = class="num">10;

   for (; ; )
   {
      if (((info / class="num">5) * class="num">5) == info) Print("Press ESC to finish counting...");
      info = info - class="num">1;
      Sleep(class="num">200);
      Print(__FUNCTION__, " : ", info);
      if (TerminalInfoInteger(TERMINAL_KEYSTATE_ESCAPE)) class="kw">break;
   }

   Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
}
class=class="str">"cmt">//+------------------------------------------------------------------+

画得少,看得清

FOR 循环是 MT5 里最容易被低估的基础结构,它把计数、条件、步进压进同一行,写错一个分号就可能让 EA 在回测里空跑几千根 K 线。前面几篇的示例大多用 WHILE 凑数,你回去把那些循环改成 FOR,编译后看执行时间和日志条数,通常能砍掉 20%~40% 的冗余输出。 外汇和贵金属杠杆高、滑点随机,任何控制结构上的低效都会放大实盘风险,所以别等写复杂策略才补这块课。 剩下几个基础概念还会更贴近实战,但底子全是这一节铺的。关掉网页,开 MT5 把附件里的 Anexo.zip 解出来跑一遍,比看十篇顺更强。

常见问题

初值放外面只在进入前赋值一次,若循环体内改了控制变量或中途跳出不复位,下次进循环就不会重新从初值跑,打印数量会偏少或重复,建议把初值写进 for 头里。
按「先初值、再条件判断、再循环体、最后自增」的顺序拆,条件为假就直接退出,用打印 i 的值能直观看到控制流走向。
可以,把代码贴给小布,它会指出循环头空白或条件永远为真的地方,并给出改成有限次数的写法。
条件部分空着默认视为真,没有自增去改变控制变量,就会一直执行循环体,变成无限循环,至少补上退出条件或步长。
只循环计算并画出关键价位或信号点,非必要的不创建对象,控制循环次数和绘制分支,图表会更干净也更快。