我发现了Fortran中的下一个有趣的事情。如下面的代码示例所示。
我不明白,也没发现为什么标签10和12上的代码可以正常工作,而标签11和13上的代码不能正常工作。
implicit none
integer :: i
integer :: IA(8) = [(i, i=1,8)]
integer :: IP
IP = 5
10 IA(IP:2) = [11, 12] ! works
11 IA(5:2) = [11, 12] ! doesn't work
12 print *, IA(IP:IP+1) ! works
13 print *, IA(IP:2) ! doesn't work
有什么区别?
答案 0 :(得分:1)
标记为10
和11
的语句的两个版本都是错误的。
数组部分ia(5:2)
是由数组ia
的零个元素组成的数组部分。数组节ia(IP:2)
(当IP
是值为5
的变量时)是相同的。
在数组元素下标中使用文字常量时,编译器在编译时会知道可以检查左侧和右侧形状的匹配。您的编译器在这里确定ia(5:2)
的形状为[0]
,而[11, 12]
的形状为不可整合[2]
。因此,它将报告错误。
您的编译器在编译时未检测到ia(IP:2)
中带有非恒定下标的错误。但是,该代码以完全相同的方式违反了Fortran标准。您看到的看似正确的输出是不好运气。
由于您曾经使用的编译选项,或者由于编译器未(正确)应用形状测试,因此您的编译器可能在运行时未检测到错误。
其他编译器可能会抱怨,例如以下消息:
Rank 1 of constant array operand has extent 2 instead of 0
Program terminated by fatal error
Abort (core dumped)
带有声明
print *, IA(IP:2)
这可以“工作”(在其他正确形成的程序中)。但是,它遭受的误解与以前完全一样。
与两个元素ia
相比,此print语句打印出ia(5:6)
的零个数组元素。而不是“不工作”,缺少明显的输出是正确地不打印任何内容/空白行。
最后,ia(5:2)
不是对ia(5)
之后的两个元素的引用。为此,您需要ia(5:6)
或ia(ip:ip+1)
。下标都是界限,不是界限和计数。