use*_*376 5 fortran fortran90 do-loops
我很惊讶你不能把一个数组成员作为do循环的控制变量,如下所示:
program test
integer, dimension(2) :: i
do i(1) = 1, 3
do i(2) = 1, 3
! anything here
write(*, *) i
end do
end do
end program
Run Code Online (Sandbox Code Playgroud)
我的问题是为什么不允许这样做?
编辑: 或是允许但我做错了?
来自ifort v 11.1的错误消息是:
test.f90(4): error #5082: Syntax error, found IDENTIFIER 'I' when expecting one of: ( % : . = =>
do i(1) = 1, 3
-------^
test.f90(4): error #5082: Syntax error, found ',' when expecting one of: <END-OF-STATEMENT> ;
do i(1) = 1, 3
---------------^
test.f90(5): error #5082: Syntax error, found IDENTIFIER 'I' when expecting one of: ( % : . = =>
do i(2) = 1, 3
-------^
test.f90(5): error #5082: Syntax error, found ',' when expecting one of: <END-OF-STATEMENT> ;
do i(2) = 1, 3
---------------^
test.f90(4): error #6535: This variable or component must be of a derived or structure type [DO]
do i(1) = 1, 3
----^
test.f90(4): error #6460: This is not a field name that is defined in the encompassing structure. [I]
do i(1) = 1, 3
-------^
test.f90(8): error #6099: An ENDDO statement occurred without a corresponding DO or DO WHILE statement.
end do
----^
test.f90(9): error #6099: An ENDDO statement occurred without a corresponding DO or DO WHILE statement.
end do
----^
Run Code Online (Sandbox Code Playgroud)
来自gfortran V4.5.1和4.8.3的错误消息是:
test.f90:4.4:
do i(1) = 1, 3
1
Error: Unclassifiable statement at (1)
test.f90:5.4:
do i(2) = 1, 3
1
Error: Unclassifiable statement at (1)
test.f90:8.7:
end do
1
Error: Expecting END PROGRAM statement at (1)
test.f90:9.7:
end do
1
Error: Expecting END PROGRAM statement at (1)
Run Code Online (Sandbox Code Playgroud)
对不起,我的第一个错误答案.
限制遵循语言规则:
Fortran 2008(ISO/IEC 1539-1:2010)8.1.6.2:
R818 循环控制 是,do-variable = ...
R819 做的变量 是,标-INT-变量名
C812(R819)do-variable应为整数类型的变量.
因此,是的,在循环控制变量的位置只允许标量变量名.
如果你问为什么语言的规则是这样的,你必须问标准的作者,SC22/WG5和X3J3,但我猜它与固定源形式的句法明确性的必要性有关.在固定的源形式中,空间并不重要,很难提出明确的语法.
Fortran 2003 及更高版本有一个称为 Associate 块的构造,在此块内,您可以将名称与任何表达式相关联。在你的例子中,它看起来有点像这样:
program test
integer, dimension(2) :: i
associate (x => i(1), y => i(2))
do x = 1, 3
do y = 1, 3
! anything here
write(*, *) i
end do
end do
end associate
end program
Run Code Online (Sandbox Code Playgroud)
本次更新i在双循环内更新。
(注:直到 @VladimirF 在下面的评论中确认这一点之前,我不确定这是否符合标准。谢谢)
弗拉基米尔F的答案是正确的,但我们可以更多地强调相关的观点.
do变量的引用语法规则是
R819 do-variable 是 scalar-int-variable-name
确切地说明这意味着什么是非常重要的.
当然,do变量必须是标量整数变量.在问题的情况下,数组元素i(1)(和i(2))是标量整数变量:数组元素是rank-0的变量.
但是,名称是另一个限制. i(1)本身并不是一个名字.我们看到了语法规则
R303 名称 是 字母 [ 字母数字字符 ] ...
超出标量整数变量的限制超出了数组元素.此外,以下可能是没有相应名称的变量:
这意味着不允许以下内容:
type t
integer i
end type t
type(t) x
do x%i=1,1 ! x%i is not a name
end do
end
Run Code Online (Sandbox Code Playgroud)
既不是
integer, target :: i
do f()=1,1
end do
contains
function f()
integer, pointer :: f
f=>i
end function
end
Run Code Online (Sandbox Code Playgroud)
但是,如chw21的回答所述,使用关联构造成功:
type t
integer i
end type
type(t) x
integer n(1)
associate (i=>x%i, j=>n(1))
do i=1,1
do j=1,1
end do
end do
end associate
end
Run Code Online (Sandbox Code Playgroud)
虽然x%i并且n(1)不是名称,但associate构造确实会创建名称:
R803 associate-stmt 是 [ associate-construct-name:] ASSOCIATE(association-list)
R804 关联 是 associate-name => selector
请注意,关联实体只是一个变量是不够的.
同样,如果有名称,则允许指针:
type t
integer i
end type
type(t), target :: x
integer, target :: n(1)
integer, pointer :: i, j
i => x%i
j => n(1)
do i=1,1
do j=1,1
end do
end do
end
Run Code Online (Sandbox Code Playgroud)
同样,i和j这里的名字.
为了兴趣,NAG编译器将指针和关联实体标记为变量为"可疑".实际上,必须特别注意避免改变循环变量.