5

我很惊讶您不能像这样将数组成员作为 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

我的问题是为什么不允许这样做?

编辑: 还是允许但我做错了?

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
----^

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)
4

3 回答 3

6

Vladimir F 的回答是正确的,但我们可以再强调一点。

do 变量的引用语法规则是

R819 do-variable scalar-int-variable-name

准确地指出这意味着什么是非常重要的。

do 变量当然必须是标量整型变量。在问题的情况下,数组元素i(1)(和i(2))是一个标量整数变量:数组元素是秩为 0 的变量。

但是,名称是进一步的限制。 i(1)本身不是一个名字。我们看到语法规则

R303名称 字母[ alphanumeric-character ] ...

这种超出标量整数变量的限制超出了数组元素。此外,以下可能是没有对应名称的变量:

  • 派生类型的组件;
  • 具有指针结果的函数(Fortran 2008 中的变量,而不是之前的变量)。

这意味着不允许执行以下操作:

type t
  integer i
end type t
type(t) x

do x%i=1,1   ! x%i is not a name
end do

end

既不是

integer, target :: i
do f()=1,1
end do

contains
  function f()
    integer, pointer :: f
    f=>i
  end function
end

但是,正如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

尽管x%iandn(1)不是名称,但该associate构造确实创建了名称:

R803 associate-stmt [ associate-construct-name :] ASSOCIATE (关联列表)

R804关联 associate-name =>选择器

请注意,关联实体只是一个变量是不够的。

同样,如果有名称,则允许使用指针:

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

再一次,i这里j是名字。

出于兴趣,NAG 编译器将使用指针和关联实体标记为“有问题的”变量。实际上,必须格外小心以避免更改循环变量。

于 2018-04-19T14:19:47.447 回答
5

对不起,我的第一个错误答案。

限制遵循语言规则:

Fortran 2008 (ISO/IEC 1539-1:2010) 8.1.6.2:

R818循环控制 , do-variable = ...

R819 do-variable is , scalar-int-variable-name

C812 (R819) do-variable 应该是一个整数类型的变量。

因此,是的,在循环控制变量的位置只允许使用标量变量名称。

如果你问为什么语言的规则是这样的,你必须问标准的作者,SC22/WG5 和 X3J3,但我猜这与固定源形式的句法明确性的必要性有关。在固定源形式中,空格并不重要,很难提出明确的语法。

于 2014-10-28T07:20:09.013 回答
4

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

i在双循环内更新。

(注意:在@VladimirF 在下面的评论中确认之前,我不确定这是否符合标准。谢谢)

于 2018-04-19T01:49:13.413 回答