从基础到中级:FOR 语句·进阶篇
for循环初值放错位置的打印差异
这段脚本演示了同一个计数循环,仅因初始化表达式写法不同,输出序列就会出现明显偏移。第一段代码在 for 里用空初始化,循环体前先 Print 了一次 info=10,随后从 10 递减到 1 打印,共 10 次循环打印。 第二段把 info=info-1 写进 for 的初始化段,进入循环时 info 已变成 9,最终只从 9 打印到 1,少打了一个数。两种写法在 MT5 里跑出来的日志行数差 1 行,肉眼能直接核对。 外汇与贵金属 EA 调试时,这种边界差最容易让仓位计数或重試次数偏离预期,属于高风险环境下的隐性 bug。开 MT5 新建脚本粘下面代码,切到 Experts 标签就能看前后两段输出对比。
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 终端陷入不受控挂起,属高风险操作,上机前务必确认退出路径。
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 解出来跑一遍,比看十篇顺更强。