我知道计算机科学通常对GOTO语句不满意,但是通过使用它可以获得速度上的优势
INTEGER WHICH
GOTO(100,200,300) WHICH
100 do something
GOTO 400
200 do something else
GOTO 400
300 do a third thing
GOTO 400
400 CONTINUE
与
INTEGER WHICH
IF(WHICH.EQ.1)THEN
do something
ELSEIF(WHICH.EQ.2)THEN
do something else
ELSEIF(WHICH.EQ.3)THEN
do a third thing
ENDIF
因为Fortran缺少SWITCH语句?
答案 0 :(得分:2)
首先,作为一般性评论,这类微优化确实不值得您花费时间。问题的答案更为重要:什么更易于调试,理解和迁移?
必填项:GOTO still considered harmful?
话虽如此,不幸的是,我必须通知您OP的代码示例中有一个错误(猛禽在这里)。您使用的计算出的GOTO语句具有以下属性:
执行已计算的GOTO语句将导致对标量整数表达式进行求值。如果此值为 i ,使得 1≤i≤n 其中 n 是label-list中的标签数,分支到由列表中 i th 标签标识的分支目标语句标签。 如果 i 小于 1 或大于 n ,则执行顺序将继续,就像执行了CONTINUE语句一样。
这意味着正确的版本应为:
INTEGER WHICH
GOTO(100,200,300) WHICH
GOTO 400 << missing part
100 do something
GOTO 400
200 do something else
GOTO 400
300 do a third thing
GOTO 400
400 CONTINUE
当生成以下3个文件的汇编代码(见下文)时,您实际上会注意到在优化下汇编代码是相同的。您可以使用bash脚本中的以下几行来快速检查自己:
$ for i in f{1,2,3}.f90; do ifort -O3 -S $i; done
$ meld f{1,2,3}.s
您还将注意到,如果删除了缺少的goto 400
,则通过一些说明,goto汇编代码将更快。
f1.f90的来源:
subroutine g(a)
integer a
goto(100,200,300) a
goto 400
100 call f1()
goto 400
200 call f2()
goto 400
300 call f3()
goto 400
400 continue
end subroutine g
f2.f90的来源:
subroutine g(a)
integer a
if(a.eq.1)then
call f1()
elseif(a.eq.2)then
call f2()
elseif(a.eq.3)then
call f3()
endif
end subroutine g
f3.f90的来源:
subroutine g(a)
integer a
select case (a)
case (1)
call f1()
case (2)
call f2()
case (3)
call f3()
end select
end subroutine g