'条件分支--'GoTo' Kluge ? - 页 4

 

Java也不能在其虚拟机 之外运行,在那里你会遇到同样的问题,你不能制作一个可以从C程序中加载和调用的dll。

如果你喜欢C#,那么你也会喜欢ObjectPascal(类型安全、严格性、它背后的整个哲学,除了虚拟机的事情)。毕竟C#的设计者和首席架构师是曾经创造了Turbo-Pascal和Delphi(ObjectPascal)的同一个人,这一点非常明显。在某些方面,C#就像ObjectPascal与(丑陋但现在很时髦的)C语法。

对于直接与机器和C-API接口(如MetaTrader所需要的),并且仍然使用像C#这样强大的语言,除了ObjectPascal之外,没有太多的替代品。有人说C++同样强大(当然也可以用来代替OP),但它显然没有那么优雅,有很多不一致的地方,而且很容易出错,只有真正的专家才能真正掌握它。

 
7bit:

.... 在一个函数内的返回将使它返回到函数被调用的地方。

这是关键的区别,7bit。我说的是在整个当前函数之外调用一个完全不同的函数、子程序甚至是导入的代码、整个子程序和/或函数。一个概念性的例子。

我在一个从第100行到第20行的函数中,但我想调用这个范围之外的东西。 也许是一个完全不同的函数,在第50到60行。 <=-这不符合上面 的参数和例子,这就是我所问的。 这是一个100%替代旧的gosub/return的函数,另外这个函数允许传递值和返回值。

你可以在同一个函数内有多个返回语句,你也可以用break....,脱离循环

明白了

但我一直被告知,我可以在一个特定函数的范围内 移动,这我理解。但这根本不是我所问的,而且在这一切的开始就已经说了。

至于 "例外",我想如果你愿意,你可以这样称呼它们。 正如我所说的,我试图找到一个 "解决方法 "来增加和利用一些功能,如。GoTo、GoSub(在CURRENT函数之外)等功能,这些功能在MQL4中并不直接作为一个函数存在。 从你们的回答来看,你们中的大多数人都知道并理解这些编程的区别,但没有解决所问的实际问题。

 

FourX:

我在一个从第100行到第20行的函数中,但我想调用这个范围之外的东西。也许是一个完全不同的函数,在第50至60行。
创建一个单独的函数,包含第50-60行的代码,然后你可以随时从你所在的任何其他函数中调用它。
 

考虑这个问题。

void foo(){
  int x;
  int y;
  y = 33;
  x = 42;
  .LABELFOO
  print(x);
  return;
}

void bar(){
  int x;
  z = 5;
  GOTO .LABELFOO
}

void main(){ //<-- program starts here
  foo();
  bar();
}

现在会发生什么?让我们从main()开始,我将解释执行过程中的所有步骤(注释为绿色,指令为黑色)。

  • (我们在main()的第一行)
  • 将返回地址推入堆栈(需要4个字节),这是调用foo()后继续执行的地址(我们需要记住这一点,以便以后知道该返回到哪里)。
  • 跳转到foo()的第一行
  • 向堆栈推4个字节,为局部变量x腾出空间
  • 向堆栈推送4个字节,为本地变量y腾出空间
  • (我们的堆栈现在有12个字节高)
  • 将长值33写到0,1,2,3字节中(从堆栈顶部算起)
  • 将长值42写入字节4,5,6,7(从堆栈顶部开始计算)
  • 打印在4,5,6,7字节中找到的长值(从堆栈顶部算起)
  • 从堆栈中弹出4个字节并忘记它们(y超出了范围)
  • 从堆栈中弹出4个字节并忘记它们(x超出范围)。
  • 从堆栈中弹出4个字节,这是我们调用foo()时的地址,也就是返回地址,跳转到这个地址
  • (现在我们又回到了main()的下一行,即bar()的那一行)
  • 将返回地址(4字节)推送到堆栈
  • 跳转到bar()的第一行
  • 将4个字节(局部变量x)推到堆栈中
  • (我们的堆栈现在有8个字节高了)
  • 将长值5写到0,1,2,3字节(从堆栈顶部算起)。
  • 跳转到标签.LABELFOO
  • (现在仔细观察一下,从这里开始,一切都会出现可怕的错误。我们已经知道下面所有的行会做什么,因为我在上面解释过了,它们做的事情和之前的完全一样,它们都表现得好像它们有堆栈的前12个字节可以支配。但这次堆栈只有8个字节!下一行期望在堆栈顶部的4,5,6,7位置有一个变量,现在让我们看看会发生什么,这里是带有print的一行)
  • 打印在4,5,6,7字节中发现的长值(从堆栈顶部算起)。
  • (哎呀,这不是我们的X,这是返回值,这次堆栈只有8字节高,它打印的是一个完全无意义的数字)
  • 从堆栈中弹出4个字节并忘记它们(这将是 "y超出范围",但它不是y,实际上是另一个函数的x)
  • 从堆栈中弹出4个字节并忘记它们(这将是 "x超出范围",但它不是x,我们刚刚扔掉了返回地址!)。
  • (堆栈现在是空的!)。
  • 从堆栈中弹出4个字节以获得返回地址------崩溃!你能看到吗?

你能看到吗?foo函数需要一个8字节加上返回地址的本地堆栈框架,bar函数 只需要4字节加上返回地址。它们的返回语句在编译时就已经被编译器内置了,它们从堆栈中弹出不同数量的字节,你不能用一个返回语句来做另一个的工作,每个返回语句只对它被编译的函数起作用。

这些在整个程序中都有GOTO的老语言没有局部变量范围,你唯一要做的就是把GOSUB和RETURN的数量匹配起来,使之相等,他们所有的返回都只弹出返回地址,没有其他的,所有的返回行为都完全一样。但是现在我们有很多不同大小的 "GOSUB"(每个GOSUB在堆栈中的推送量不同),也有很多不同的返回,从堆栈中弹出不同的量。而且我们在栈上还有局部变量。这是不可能的,不管你试图在编译器中建立什么疯狂的东西。

理论上,你可以在同一个函数中使用GOTO(有些语言允许这样做),但你不能告诉我有哪一段代码会比适当的结构化编程更优雅、更容易理解和更容易维护。它所做的只是产生一个可怕的混乱。没有人需要这个,所以它没有被实现。

 

我们都已经知道,MQL4没有像GoTo 或'GoSub-=>ReturnFromGoSub'这样的本地函数。 对这一点没有争议。现在这已经变成了反复解释和举例说明MQL4没有这样的本地函数。 这一点没有争议。 这不是这个主题的内容,它从来都不是。所以,我们能不能不要再争论我们已经知道和同意的事情?

我们知道,这些函数在其他编程语言中是有效的,而且可以非常有用。

这个问题的重点是要找出我们是否可以用MQL4中的可用功能来模拟和利用它们?

例如,第一句话中"GoSub-=>ReturnFromGoSub"的第二种情况的有效函数完成是。返回到GoSub被调用的程序点,并将GoSub的值返回到程序中的调用点

 
FourX:

例如,"GoSub-=>ReturnFromGoSub"第一句中第二种情况的有效函数完成是:。返回到GoSub被调用的程序点,并将GoSub的值返回到程序中的调用点。


你已经多次被告知,你所描述的是一个自定义函数......为什么你不能接受呢?请举一个例子,用伪代码说明为什么自定义函数!=Gosub + Return
 

FourX:

'GoSub-=>ReturnFromGoSub'会是这样。返回到GoSub被调用的程序点,并将GoSub的值返回到程序中的调用点。

double subtract_two_numbers(double a, double b){
  Print("will now calculate ", a, " minus ", b);
  return(a - b);                                 // <---- THIS IS YOUR RETURN
}

int start(){                                     // <---- PROGRAM STARTS HERE
  double s;
  double d;

  s = subtract_two_numbers(Ask, Bid);            // <---- THIS IS YOUR GOSUB
  d = subtract_two_numbers(Close[0], Open[0]);   // <---- THIS IS YOUR GOSUB

  Print("the spread is ", s);
  Print("price moved ", d, " since the open");
}                                                // <---- PROGRAM ENDS HERE
你有你的GOSUB和RETURN,就在mql4语言中,甚至可以传递参数和返回值,这在Commodore-BASIC或其他你不断试图比较的古老而残缺的语言中是不可能的。在过去的30年里,你都去哪儿了?
 

FourX如果你在学习mql4的时候,你的思维还停留在BBC Basic上,想想defproc和proc,忘掉GoTo和GoSub。

我在80年代初有一台BBC micro,....ahhhh,我还记得试图让程序从磁带机上加载的乐趣:(我们曾经用BBC Basic编写程序

 
SDC:

FourX如果你在学习mql4的时候,你的思维还停留在BBC Basic上,想想defproc和proc,忘掉GoTo和GoSub。

我在80年代初有一台BBC micro,....ahhhh,我还记得试图让程序从磁带机上加载的乐趣:(我们曾经用BBC Basic编写程序

大笑.. . 我有一台Acorn Electron ......当它热的时候,它不会读出我在冷的时候写的带子上的东西,反之亦然......那些日子里,;-)
 
RaptorUK:
LOL .. .我有一台Acorn Electron ......当它热的时候,它不会读出我在冷的时候写的带子上的东西,反之亦然......那些日子就是这样。)

是的,那是一段美好的日子:)用一把弯曲的螺丝刀拧住磁带头旁边的小螺丝,同时反复敲打它的侧面,哈哈。