从基础到中级:IF ELSE·进阶篇
📘

从基础到中级:IF ELSE·进阶篇

第 2/2 篇

条件恒真与恒假的三种写法

在 MQL5 脚本里,if 分支的判定条件并不总按直觉走。下面三段 OnStart 演示了三种让代码必然或绝不进入分支的写法,直接丢进 MT5 的脚本文件就能跑出日志。 第一段用 if(false),第 9 行的 Print 永远不会执行,而第 6、11 行的两句照常打印。日志里你只会看到两次 'It will be executed anyway...',验证分支被跳过。 第二段把 false 取反写成 if(~false),按位非让条件变成非零值,分支必然进入,第 9 行 'True condition...' 会出现在两次常规打印之间。 第三段用 if(false | true),按位或只要有一侧为真整体即真,日志会输出 'A very crazy condition always true ...'。外汇与贵金属杠杆高,这类恒真/恒假陷阱在 EA 风控判断里可能让止损逻辑被静默绕过,实盘前务必逐行核对条件表达式。

MQL5 / C++
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)
{
   Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");

   if (false)
      Print("True condition...");

   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)
{
   Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");

   if (~false)
      Print("True condition...");

   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)
{
   Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");

   if (false | true)
      Print("A very crazy condition always true ...");

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

「ELSE 必须配对,别想单独跑」

不少自学 MQL5 的人会犯一个低级错:把 ELSE 当成能独立存在的语句。实际上 ELSE 只是「否则」分支,必须挂在另一个语句后面。很多人以为它只认 IF,但在 SQL 里 ELSE 是跟 CASE 绑定的——语言设计不同,细节就不同,别拿一门语言的直觉硬套另一门。 在 MQL5 里,只要 ELSE 和 IF 成对,IF 条件为假时才走 ELSE 块。逻辑本身不复杂,但真写起来容易漏掉配对,尤其嵌套多层时。 下面这段代码把 IF-ELSE 和引用传参揉在一起。第 6 行定义 int info = 10;第 10 行 if(info) 为真(非零即真),调用 Procedure 把 info 改成 0 并打印两次;第 12 行 else 此时不执行。第 15 行再次 if(info),但 info 已被改成 0,条件为假,于是第 17 行 else 输出 False condition。第 8 行和第 20 行是无论分支如何都会打印的锚点。 [CODE]

  • //+------------------------------------------------------------------+
  • #property copyright "Daniel Jose"
  • //+------------------------------------------------------------------+
  • void OnStart(void)
  • {
  • int info = 10;

07.

  • Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway... #1 => ", info);

09.

  • if (info)
  • Procedure(info);
  • else
  • Print("Variable info is equal to zero...");

14.

  • if (info)
  • Print("True condition...");
  • else
  • Print("False condition...");

19.

  • Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway... #2 => ", info);
  • }
  • //+------------------------------------------------------------------+
  • void Procedure(int & arg1)
  • {
  • Print(__FUNCTION__, " ", __LINE__, " #1 => ", arg1);
  • arg1 = 0;
  • Print(__FUNCTION__, " ", __LINE__, " #1 => ", arg1);
  • }
  • //+------------------------------------------------------------------+

[/CODE] 逐行拆解:06 声明变量并赋 10;08 打印首条必执行信息;10 判断 info 非零进入 if;11 调用 Procedure 传引用;12-13 是配对 else,本次跳过;15 二次判断 info 此时已为 0;16 与 17-18 分别对应真假分支,本次走 else;20 打印末条必执行信息;23-28 的 Procedure 接收引用,25 打印传入值,26 改为 0,27 打印改后值。 开 MT5 把第 6 行改成 int info = 0 跑一遍,你会看到第 11 行不执行、第 13 行输出「Variable info is equal to zero...」,而第 15 行依旧走 else。外汇与贵金属杠杆高、风险大,这类逻辑练习请在策略测试器用离线数据验证,别直接挂实盘。

MQL5 / C++
class="num">01. class=class="str">"cmt">//+------------------------------------------------------------------+
class="num">02. class="macro">#class="kw">property copyright "Daniel Jose"
class="num">03. class=class="str">"cmt">//+------------------------------------------------------------------+
class="num">04. class="type">void OnStart(class="type">void)
class="num">05. {
class="num">06.     class="type">int info = class="num">10;
class="num">07. 
class="num">08.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway... #class="num">1 => ", info);
class="num">09. 
class="num">10.     if (info)
class="num">11.         Procedure(info);
class="num">12.     else
class="num">13.         Print("Variable info is equal to zero...");
class="num">14. 
class="num">15.     if (info)
class="num">16.         Print("True condition...");
class="num">17.     else
class="num">18.         Print("False condition...");
class="num">19.     
class="num">20.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway... #class="num">2 => ", info);
class="num">21. }
class="num">22. class=class="str">"cmt">//+------------------------------------------------------------------+
class="num">23. class="type">void Procedure(class="type">int & arg1)
class="num">24. {
class="num">25.     Print(__FUNCTION__, " ", __LINE__, " #class="num">1 => ", arg1);
class="num">26.     arg1 = class="num">0;
class="num">27.     Print(__FUNCTION__, " ", __LINE__, " #class="num">1 => ", arg1);
class="num">28. }
class="num">29. class=class="str">"cmt">//+------------------------------------------------------------------+

◍ ELSE 挂错 IF 是 MQL5 里的隐形坑

纯嵌套 IF 不算麻烦,MQL5 里真正容易翻车的是 IF 和 ELSE 混排时的归属歧义。缩进在 MQL5 中只是给人看的,编译器根本不认,第 18 行的 ELSE 永远贴着最近的那个 IF(第 16 行),而不是你视觉上以为的第 14 行。 下面这段就是典型陷阱:c1=10、c2=0、c3=-6、c4=3,四个 IF 串起来,最后甩一个 ELSE。你以为 ELSE 对应最外层 c1 的判断,实际它只接 c4 那个 IF。跑起来若 c1 为真但 c4 为假,就会掉进 ELSE 子程序,逻辑完全偏掉。 [CODE] //+------------------------------------------------------------------+ #property copyright "Daniel Jose" //+------------------------------------------------------------------+ void OnStart(void) { char c1 = 10, c2 = 0, c3 = -6, c4 = 3; Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway..."); if (c1) if (c2) if (c3) if (c4) Print("True condition..."); else Print("False condition..."); Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway..."); } //+------------------------------------------------------------------+ [/CODE] 逐行拆解:第 06–09 行定义四个 char 变量,非零即真;第 13 行 if(c1) 进内层;第 14–16 行继续嵌套判断;第 17 行才是那个 else,它编译时绑定第 16 行 if(c4),跟 c1/c2/c3 无直接隶属。 最稳的修法是显式加花括号把子块框死,让编译器 unambiguous:把第 14 行 IF 连同里面所有内容包进一个 block,ELSE 自然就挂回外层了。另一种写法靠连续 else if 硬链,结果等价但可读性差,教学里能看懂就行,实盘策略代码别这么绕。 开 MT5 把上面代码贴进脚本跑一遍,故意让 c4=0,看输出是不是进了 else——这一下就能确认你当前环境里 ELSE 的绑定规则,比看文档直观。

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 c1 = class="num">10,
         c2 = class="num">0,
         c3 = -class="num">6,
         c4 = class="num">3;

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

    if (c1)
        if (c2)
            if (c3)
                if (c4)
                    Print("True condition...");
        else
            Print("False condition...");

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

嵌套 if 与逻辑与的等价陷阱

把多个条件用 && 串成一行,和把它们写成层层缩进的 if 嵌套,在 MQL5 里控制流走向并不总是一回事,尤其当某个中间变量为 0 时。上面第一段用 if ((c1) && (c2) && (c3) && (c4)) 判断,c2 赋值为 0,整个布尔表达式短路,不会打印 "True condition...",但函数末尾那行 Print 照常执行。 第二段代码把四个变量拆成四级 if 嵌套:c1=10 为真进入,c2=0 为假,直接命中 else 分支打印 "False condition..."。这里要注意,else 只绑定最内层的 if (c2),而不是后面某个条件,这种缩进若没大括号极易看错归属。 第三段在 c2 为假处补了 {} 把后续 c3、c4 的判断关在里面,于是 c2=0 时整块子树被跳过,不会再向下求值。实盘策略里若用多个指标阈值做过滤,建议显式加 {} 而非依赖缩进,MT5 回测时少踩这类静默逻辑坑——外汇与贵金属波动剧烈,错误条件分支可能导致信号频率异常偏高。 开 MT5 新建脚本粘入下方代码,改 c2 为 1 或 -1,对比三段输出的行号与打印内容,能直观看到短路与嵌套的差异。

MQL5 / C++
class="type">void OnStart(class="type">void)
{
   class="type">char c1 = class="num">10,
        c2 = class="num">0,
        c3 = -class="num">6,
        c4 = class="num">3;

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

   if ((c1) && (c2) && (c3) && (c4))
      Print("True condition...");

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

class="type">void OnStart(class="type">void)
{
   class="type">char c1 = class="num">10,
        c2 = class="num">0,
        c3 = -class="num">6,
        c4 = class="num">3;

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

   if (c1)
      if (c2)
         if (c3)
            if (c4)
               Print("True condition...");
         else
            Print("False condition...");

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

class="type">void OnStart(class="type">void)
{
   class="type">char c1 = class="num">10,
        c2 = class="num">0,
        c3 = -class="num">6,
        c4 = class="num">3;

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

   if (c1)
      if (c2)
      {
         if (c3)
            if (c4)
               Print("True condition...");
      }

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

「嵌套 if 里空 else 的坑」

上面这段 MT5 脚本演示了 char 变量在条件判断里的隐式转换。c1=10、c2=0、c3=-6、c4=3,四个变量连续嵌套 if,只有 c1 非零时才会进入第二层;c2 为 0 直接走 else 分支打印 "False condition..."。 注意第 18、19 行的 else; 是空语句。很多人以为不写 else 就完了,但在多层嵌套里留个空 else 能明确语法归属,避免后面维护时把层次看错。 无论条件怎么走,第 11 行和第 23 行的 Print(__FUNCTION__, __LINE__, ...) 都会执行——这是验证代码确实跑过 OnStart 的笨办法。开 MT5 新建脚本粘进去,终端里能看到两次 "It will be executed anyway..." 以及一次 "False condition...",说明 c2=0 把链切断了。 外汇和贵金属行情跳动快,这类控制流逻辑若写错层级,实盘里的订单触发条件可能完全偏离预期,务必在策略测试器里先跑通再上真金白银。

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 c1 = class="num">10,
        c2 = class="num">0,
        c3 = -class="num">6,
        c4 = class="num">3;

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

   if (c1)
      if (c2)
         if (c3)
            if (c4)
               Print("True condition...");
            else;
         else;
      else
         Print("False condition...");

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

◍ 写出自己的 MQL5 控制流风格

控制流语句刚接触时容易绕晕,但耐心练下去,能为同一问题找出少数人才想得到的写法。已解决的代码不代表最优,同一逻辑常存在更省资源的解法,学会越过第一眼能看到的方案才算入门。 附件 ZIP 仅 2.64 KB,未打包全文代码,但读完你完全能手动补全并改写。除了练手,更重要的是形成自己的编程语气——同样功能,不同人写的嵌套与缩进差异很大。 让代码能被别人读懂,也让你自己改起来快,这一步比抄完示例更有长期价值。外汇与贵金属 EA 编写属高风险活动,实盘前务必在 MT5 策略测试器充分验证。

常见问题

可用 if(true) 恒真、if(false) 恒假,或直接 if(1) 恒真、if(0) 恒假;第三种是把变量赋成固定值再判断,调试时临时屏蔽分支很好用。
不能。else 必须紧跟配对的 if,单独写会直接编译失败;检查是不是漏了上面的 if 花括号或把 else 写进了别的作用域。
可以。把源码贴给小布,它能标出 else 实际配对的 if 行,并提示嵌套层级里空 else 造成的逻辑漏洞,省去肉眼数括号。
不一定。嵌套 if 在上一层不成立时会跳过内层,而逻辑与会整体求值;空 else 缺失时两者分支覆盖差异会悄悄改变执行路径。
先死磕 else 必配对、嵌套别超三层、空 else 显式留注释;风格化前先保证配对和层级一眼能看懂,再谈简写。