Using array member as the control variable of do l

2019-02-22 15:33发布

I was surprised that you cannot put a array member as the control variable of do loop like this:

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

My question is why it is not permitted?

Edit: Or is it permitted but I am doing wrong?

The error message from ifort v 11.1 is:

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

The error message from gfortran V4.5.1 & 4.8.3 is:

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)

3条回答
疯言疯语
2楼-- · 2019-02-22 15:40

Sorry for my first wrong answer.

The restriction follows from the rules of the language:

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

R818 loop-control is, do-variable = ...

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

C812 (R819) The do-variable shall be a variable of type integer.

Therefore yes, only a scalar variable name is permitted at the position of the loop control variable.

If you ask why the rules of the language are like this, you have to ask the authors of the standard, the SC22/WG5 and X3J3, but I would guess it is connected with the necessity of syntactic unambiguity in the fixed-source form. In the fixed source form spaces are not significant and it is difficult to come up with an unambiguous grammar.

查看更多
虎瘦雄心在
3楼-- · 2019-02-22 15:45

Vladimir F's answer is correct, but we can stress a little more the pertinent point.

The quoted syntax rule for the do variable is

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

and it's very important to note exactly what this means.

It is of course necessary for the do variable to be a scalar integer variable. In the case of the question the array element i(1) (and i(2)) is a scalar integer variable: array elements are variables of rank-0.

However, name is a further restriction. i(1) is not itself a name. We see the syntax rule

R303 name is letter [ alphanumeric-character ] ...

This restriction beyond scalar integer variable goes beyond array elements. In addition, the following may be variables which do not have corresponding names:

  • components of derived types;
  • functions with pointer results (a variable as of Fortran 2008, not before).

This means that the following is not allowed:

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

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

end

Neither is

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

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

However, as noted in chw21's answer there is success with using an associate construct:

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

Although x%i and n(1) are not names, the associate construct does create names:

R803 associate-stmt is [associate-construct-name :] ASSOCIATE (association-list)

R804 association is associate-name => selector

Note that the associate entity being simply a variable is not sufficient.

Equally, pointers are allowed, if there is a 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

Again, i and j here are names.

For interest, the NAG compiler marks using pointer and associate entities as do variables as "questionable". Indeed, one has to take extra care to avoid changing the loop variable.

查看更多
\"骚年 ilove
4楼-- · 2019-02-22 15:56

Fortran 2003 and later has a construct called an Associate block, where, inside this block, you can associate a name with any expression. In your case, it looks a bit like this:

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

This updates i inside the double loop.

(Note: Until @VladimirF confirmed it in a comment below, I wasn't certain whether this was standard conform. Thanks)

查看更多
登录 后发表回答