Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Can a scalar variable appear more than once as a READ input item?

101 views
Skip to first unread message

Beliavsky

unread,
Mar 29, 2022, 9:19:46 PM3/29/22
to
The program

program main
implicit none
character (len=100) :: text
integer :: i,j(1)
text = "2 4"
read (text,*) i,i
read (text,*) j(1),j(1)
print*,"i=",i
print*,"j=",j
end program main

gives output

i= 4
j= 4

with gfortran and Intel Fortran. Section 10.4 of Metcalf/Reid/Cohen (2018) says

"However, no element of the array may appear more than once in an input item."

so I think

read (text,*) j(1),j(1)

is non-standard. What about reading a scalar twice, as in

read (text,*) i,i

The reason to read a variable more than once is to skip over data.

gah4

unread,
Mar 30, 2022, 1:31:23 AM3/30/22
to
On Tuesday, March 29, 2022 at 6:19:46 PM UTC-7, Beliavsky wrote:
> The program
>
> program main
> implicit none
> character (len=100) :: text
> integer :: i,j(1)
> text = "2 4"
> read (text,*) i,i
> read (text,*) j(1),j(1)
> print*,"i=",i
> print*,"j=",j
> end program main
>
> gives output
>
> i= 4
> j= 4
>
> with gfortran and Intel Fortran. Section 10.4 of Metcalf/Reid/Cohen (2018) says
>
> "However, no element of the array may appear more than once in an input item."

In the case of C and the C standard, there are many cases of "undefined behavior".

If a program does something the is UB, one is not supposed to have any expectations
about the results. Anything can happen. (Including what you most hope happens.)

There is also Implementation defined behavior. In this case, there are normally
a small number of things that can happen, which only apply to the specific part
in question.

In the case of UB, in the given case, you would not have any expectation about
the results of the program. In the case of IDB, only the specific variables in
question would be questioned.

In the latter case, you would not know the value of the specific variables listed
more than once, but other variables would be fine.

Note, for example, recent discussion on the END= or ERR= exit, which can occur
during execution of a READ statement, such that all variables listed should be
considered undefined. It would be nice to believe that earlier variables are fine,
and only later (not yet read) undefined, but the standard doesn't say that.

I suspect that you have to read the standard more carefully to understand this case.

Ron Shepard

unread,
Mar 30, 2022, 1:48:12 AM3/30/22
to
On 3/29/22 8:19 PM, Beliavsky wrote:
> The program
>
> program main
> implicit none
> character (len=100) :: text
> integer :: i,j(1)
> text = "2 4"
> read (text,*) i,i
> read (text,*) j(1),j(1)
> print*,"i=",i
> print*,"j=",j
> end program main
>
> gives output
>
> i= 4
> j= 4
>
> with gfortran and Intel Fortran. Section 10.4 of Metcalf/Reid/Cohen (2018) says
>
> "However, no element of the array may appear more than once in an input item."

I was not aware of this restriction. I checked the standard, and the
restriction is there, so MRC is correct. The example given in the
standard is an array referenced with a vector subscript, not with
literal constants, but I do not see any exception for that latter case.

> so I think
>
> read (text,*) j(1),j(1)
>
> is non-standard. What about reading a scalar twice, as in
>
> read (text,*) i,i
>
> The reason to read a variable more than once is to skip over data.

I do not see a similar restriction on repeated scalar variables in the
i/o list. I certainly see this done in practice for the reason you give,
to skip over items in the file and to ignore their values.

$.02 -Ron Shepard

Robin Vowels

unread,
Mar 30, 2022, 1:58:40 AM3/30/22
to
On Wednesday, March 30, 2022 at 12:19:46 PM UTC+11, Beliavsky wrote:
> The program
>
> program main
> implicit none
> character (len=100) :: text
> integer :: i,j(1)
> text = "2 4"
> read (text,*) i,i
> read (text,*) j(1),j(1)
> print*,"i=",i
> print*,"j=",j
> end program main
>
> gives output
>
> i= 4
> j= 4
>
> with gfortran and Intel Fortran. Section 10.4 of Metcalf/Reid/Cohen (2018) says
>
> "However, no element of the array may appear more than once in an input item."
>
> so I think
>
> read (text,*) j(1),j(1)

In this example, the first J(1) is one input item. It does not contain another reference to J.
The second J(1) is another (separate) input item. It also does not contain another reference to J.
The READ statement is therefore legal.

Thomas Koenig

unread,
Mar 30, 2022, 2:13:06 AM3/30/22
to
Beliavsky <beli...@aol.com> schrieb:
> The program
>
> program main
> implicit none
> character (len=100) :: text
> integer :: i,j(1)
> text = "2 4"
> read (text,*) i,i
> read (text,*) j(1),j(1)
> print*,"i=",i
> print*,"j=",j
> end program main
>
> gives output
>
> i= 4
> j= 4
>
> with gfortran and Intel Fortran. Section 10.4 of Metcalf/Reid/Cohen (2018) says
>
> "However, no element of the array may appear more than once in an input item."

>
> so I think
>
> read (text,*) j(1),j(1)
>
> is non-standard.

I don't think that is the case. F2018:

R1216 input-item is variable
or io-implied-do

so j(1) and j(1) are two separate input items, and the code is fine.

gah4

unread,
Mar 30, 2022, 2:23:47 AM3/30/22
to
On Tuesday, March 29, 2022 at 10:48:12 PM UTC-7, Ron Shepard wrote:
> On 3/29/22 8:19 PM, Beliavsky wrote:

(snip)

> > with gfortran and Intel Fortran. Section 10.4 of Metcalf/Reid/Cohen (2018) says

> > "However, no element of the array may appear more than once in an input item."

> I was not aware of this restriction. I checked the standard, and the
> restriction is there, so MRC is correct. The example given in the
> standard is an array referenced with a vector subscript, not with
> literal constants, but I do not see any exception for that latter case.

Yes, I also found the restriction.

Note that there are a number of different ways to use array element that
can complicate I/O. Note, for example, (though I haven't looked recently)
to do something like:

READ(1) N, (X(I), Y(I), I=1,N)

Input items can be used in later items in the I/O list. I believe there is
a restriction on things like:

READ(1) (X(I), I=1,X(3))

where an input item is otherwise used in the same implied-DO group.
Now you get to things like:

READ(1) I, X(I), J, X(J)

which we know is legal when the read-in I is different from the read-in J.
The discussed restriction suggests that it isn't if I equals J, even
though it doesn't look so much harder to process.

(snip)

> > is non-standard. What about reading a scalar twice, as in

> > read (text,*) i,i

> > The reason to read a variable more than once is to skip over data.

> I do not see a similar restriction on repeated scalar variables in the
> i/o list. I certainly see this done in practice for the reason you give,
> to skip over items in the file and to ignore their values.

Note that the standard also doesn't say what the result should be.

By the way, C has a way to skip items in formatted input, with a *.

You can say, for example:

scanf("%*f");

such that it will read, and ignore, one f format item, following the normal rules
for f format, except for storing the data. This can be part of a larger list:

scanf("%f%*f%f", &x, &z);

Since C format items don't have the fixed width that Fortran items do,
it isn't so easy to ignore by length. Using, for example, 9X would traditionally
be used to ignore some columns, but that doesn't work for UNFORMATTED.

But as your example shows, in the case of list directed, you do need a way
to ignore something.

Thomas Koenig

unread,
Mar 30, 2022, 2:26:48 AM3/30/22
to
gah4 <ga...@u.washington.edu> schrieb:
> On Tuesday, March 29, 2022 at 10:48:12 PM UTC-7, Ron Shepard wrote:
>> On 3/29/22 8:19 PM, Beliavsky wrote:
>
> (snip)
>
>> > with gfortran and Intel Fortran. Section 10.4 of Metcalf/Reid/Cohen (2018) says
>
>> > "However, no element of the array may appear more than once in an input item."
>
>> I was not aware of this restriction. I checked the standard, and the
>> restriction is there, so MRC is correct. The example given in the
>> standard is an array referenced with a vector subscript, not with
>> literal constants, but I do not see any exception for that latter case.
>
> Yes, I also found the restriction.

Note that the restriction is on an item, not an item list.

To expand on what I wrote earlier, this means that

read (10,*) a(1), a(1)

is fine, but

read (10,*) a([1,1])

or

read (10,*) (a(i/2),i=1,10)

or

read (10,*) (a(i),a(i),i=1,10)

is not.

gah4

unread,
Mar 30, 2022, 2:27:16 AM3/30/22
to
On Tuesday, March 29, 2022 at 11:13:06 PM UTC-7, Thomas Koenig wrote:

(snip)

> I don't think that is the case. F2018:

> R1216 input-item is variable
> or io-implied-do

> so j(1) and j(1) are two separate input items, and the code is fine.

Oh, so:

READ(1) (X(1), X(1), I=1,N)

would not be allowed, to ignore 2*N items.

But also:

READ(1) (X(I/2), I=2,10)

Robin Vowels

unread,
Mar 30, 2022, 6:54:09 AM3/30/22
to
On Wednesday, March 30, 2022 at 5:23:47 PM UTC+11, gah4 wrote:
> On Tuesday, March 29, 2022 at 10:48:12 PM UTC-7, Ron Shepard wrote:
> > On 3/29/22 8:19 PM, Beliavsky wrote:
> (snip)
> > > with gfortran and Intel Fortran. Section 10.4 of Metcalf/Reid/Cohen (2018) says
>
> > > "However, no element of the array may appear more than once in an input item."
>
> > I was not aware of this restriction. I checked the standard, and the
> > restriction is there, so MRC is correct. The example given in the
> > standard is an array referenced with a vector subscript, not with
> > literal constants, but I do not see any exception for that latter case.
> Yes, I also found the restriction.
>
> Note that there are a number of different ways to use array element that
> can complicate I/O. Note, for example, (though I haven't looked recently)
> to do something like:
>
> READ(1) N, (X(I), Y(I), I=1,N)
>
> Input items can be used in later items in the I/O list. I believe there is
> a restriction on things like:
>
> READ(1) (X(I), I=1,X(3))
>
> where an input item is otherwise used in the same implied-DO group.
> Now you get to things like:
>
> READ(1) I, X(I), J, X(J)
>
> which we know is legal when the read-in I is different from the read-in J.
> The discussed restriction suggests that it isn't if I equals J, even
> though it doesn't look so much harder to process.

This is legal. See earlier discussion.
X(J) is an element, and contains only one reference to X(J).

Beliavsky

unread,
Mar 30, 2022, 7:01:56 AM3/30/22
to
On Wednesday, March 30, 2022 at 2:26:48 AM UTC-4, Thomas Koenig wrote:
> Note that the restriction is on an item, not an item list.
>
> To expand on what I wrote earlier, this means that
>
> read (10,*) a(1), a(1)
>
> is fine, but
>
> read (10,*) a([1,1])
>
> or
>
> read (10,*) (a(i/2),i=1,10)
>
> or
>
> read (10,*) (a(i),a(i),i=1,10)
>
> is not.

Thanks. That explains why for the code

program main
implicit none
character (len=100) :: text
integer :: i,j(1),k(1)
text = "2 4"
read (text,*) i,i
read (text,*) j(1),j(1)
read (text,*) k([1,1])
print*,"i=",i
print*,"j=",j
print*,"k=",k
end program main

gfortran complains only about one of the lines, saying

read_items.f90:8:17-19:

8 | read (text,*) k([1,1])
| 1 2
Error: Elements with the same value at (1) and (2) in vector subscript in a variable definition context (item in READ)

ifort, flang, and g95 do not say anything and give output

i= 4
j= 4
k= 4

Ron Shepard

unread,
Mar 30, 2022, 1:34:33 PM3/30/22
to
On 3/30/22 12:31 AM, gah4 wrote:
> On Tuesday, March 29, 2022 at 6:19:46 PM UTC-7, Beliavsky wrote:
[...]
> Note, for example, recent discussion on the END= or ERR= exit, which can occur
> during execution of a READ statement, such that all variables listed should be
> considered undefined. It would be nice to believe that earlier variables are fine,
> and only later (not yet read) undefined, but the standard doesn't say that.

I think the reason dates back to the characteristics of the first hard
disks. A READ statement might require data from multiple sectors on the
disk, or for multiplatter disks, even data from multiple surfaces within
a cylinder. When the READ statement is processed, the entire layout on
the disk for all the data was determined. Then the data transfer was
coordinated with the current location of the spinning disk (which was
slow) so that the first available sectors were read first and where the
head movement (which was very slow) was minimized. The variables in the
i/o list could thereby be filled in almost arbitrary order, and if the
same read statement were executed multiple times, they could be filled
in a different orders each time, depending on the positions of the
spinning disk and of the head at the moment of the READ statement.

The example in this thread did not involve disk i/o, it was an internal
READ, so none of that applies. But I think the overall semantics of the
READ statement probably derive from that history.

$.02 -Ron Shepard

Ron Shepard

unread,
Mar 30, 2022, 1:41:42 PM3/30/22
to
Hmmm, this is even more complicated that I thought at first.

$.02 -Ron Shepard

Lynn McGuire

unread,
Mar 30, 2022, 1:43:53 PM3/30/22
to
Yes, we do it all the time.

Lynn

John Collins

unread,
Apr 1, 2022, 2:12:14 PM4/1/22
to
> > "However, no element of the array may appear more than once in an input item."

There must have been a reason for this restriction, and the fact that it doesn't apply to scalars. I am not happy with @Ron Shepard's suggestion that the IO list items could be filled in any order because you can read a value and then use the value to control subsequent reads in the same statement, e.g.

READ(*,*)i,(a(j),j=1,i)

Does anyone know the reason? How long has this been in the standard?

gah4

unread,
Apr 2, 2022, 2:24:24 AM4/2/22
to
On Friday, April 1, 2022 at 11:12:14 AM UTC-7, john.c...@simconglobal.com wrote:
> > > "However, no element of the array may appear more than once in an input item."
> There must have been a reason for this restriction, and the fact that it doesn't apply to scalars.

The compiler can recognize at compile time when the same scalar is used.
With variable subscripts, it is harder for the compiler.

Often, though, my feeling is that there doesn't need to be a reason for a restriction,
but a reason to remove one.

Restrictions are added when someone thinks that it might be harder
for compilers to figure out, but not actually know that.

My thoughts about PL/I is that they added features without worry about
the complications for compiler writers. Simple rules make it easier for
users, but also allow interesting things.

With ENTRY in functions, Fortran EQUIVALENCEs all the return values.
PL/I does the appropriate conversion. That might mean lots of conversion
routines that would never be called, but it makes more sense for users.

The only complication with array elements is the possibility of
them being assigned in a different order than expected.



Robin Vowels

unread,
Apr 2, 2022, 5:50:31 AM4/2/22
to
On Saturday, April 2, 2022 at 5:24:24 PM UTC+11, gah4 wrote:
> On Friday, April 1, 2022 at 11:12:14 AM UTC-7, john.c...@simconglobal.com wrote:
> > > > "However, no element of the array may appear more than once in an input item."
> > There must have been a reason for this restriction, and the fact that it doesn't apply to scalars.
> The compiler can recognize at compile time when the same scalar is used.
> With variable subscripts, it is harder for the compiler.
>
> Often, though, my feeling is that there doesn't need to be a reason for a restriction,
> but a reason to remove one.
>
> Restrictions are added when someone thinks that it might be harder
> for compilers to figure out, but not actually know that.
>
> My thoughts about PL/I is that they added features without worry about
> the complications for compiler writers. Simple rules make it easier for
> users, but also allow interesting things.
.
Some thought would have been given to implementation issues,
but in the main, the design of PL/I was to remove many of the silly and
irksome restrictions that existed in FORTRAN, and to make it easier
for the programmer to implement an algorithm.
.
For example, there were silly restrictions on what could be a subscript
in FORTRAN. In generalising that in PL/I, it was possible to use a
common routine to validate an expression and to produce the object
code (instead of a separate piece of code to syntax-check a limited
expression and to produce object code for that).
.
In PL/I, it is possible for a DO statement for a loop to have
multiple specifications for iteration. These would have been
more difficult to implement compared to a single specification.
Yet it provided greater facility to the programmer.
For example, the cocktail-shaker sort usually contains two
separate loops: one to examine elements from the first to last,
and another from last to first.
.
These can be handled by a single DO statement:

DO I = 1 TO N-1, N-1 TO 1 BY -1;
...
END;
which yields in a simpler algorithm.
.
> With ENTRY in functions, Fortran EQUIVALENCEs all the return values.
> PL/I does the appropriate conversion. That might mean lots of conversion
> routines that would never be called, but it makes more sense for users.
.
That was useful in the old days, with small memories. I doubt that much
use of that is made now.
0 new messages