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

Problem in gfortran with initialization?

107 views
Skip to first unread message

jski

unread,
Oct 17, 2012, 4:43:44 PM10/17/12
to
The routine (below) prints out:

n = 0 m = 0
n = 537 m = 537
n = 537 m = 537

Neither n nor m are declared with an attribute of "save" but they keep
their previous values? That's why I added:

n = 0
m = 0

Of course, it's possible I'm missing something?

---John

!---------------------------------------------------------------------------------------------------------------------------------
logical function RM_Read( a, istyle, infile, redefine )
real(kind=WP), allocatable, intent(out) :: a(:,:)
integer, intent(in) :: istyle
integer, intent(in) :: infile
logical, intent(in) :: redefine

integer :: n = 0
integer :: m = 0
integer :: n_file, m_file, istyle_file
integer :: i, j
integer :: irow
integer :: NumElem !no. elements written from col

write(6,*) 'n =', n, 'm =', m
call flush(unit=6)

n = 0
m = 0

if (allocated(a)) then
n = size(a, dim=1)
m = size(a, dim=2)
end if

if ((istyle <= 1) .or. (istyle > 6)) then

read(unit=infile) n_file, m_file, istyle_file

if ( istyle /= istyle_file ) then
write(*,*) 'In m_read(), matrix istyle parameter does not
match file parameters.'
RM_Read = .false.; return
end if

if ( n /= n_file .or. m /= m_file) then
if ( redefine ) then
n = n_file
m = m_file
allocate(a(n,m)) !a.resize(n,m)
else
write(*,*) 'In m_read(), matrix size parameters do not
match file parameters.'
RM_Read = .false.; return
end if
end if

read(unit=infile) a

elseif (istyle == 2) then

read(unit=infile, fmt=*) n_file, m_file, istyle_file

if ( istyle /= istyle_file ) then
write(*,*) 'In m_read(), matrix istyle parameter does not
match file parameters.'
RM_Read = .false.; return
end if

if ( n /= n_file .or. m /= m_file) then
if ( redefine ) then
n = n_file
m = m_file
allocate(a(n,m)) !a.resize(n,m)
else
write(*,*) 'In m_read(), matrix size parameters do not
match file parameters.'
RM_Read = .false.; return
end if
end if

read(unit=infile,fmt=*) a(:n,:m)

elseif (istyle == 3) then

if (n /= m) then
write(*,*) 'Matrix not symm, so sym matrix option not
available.'
RM_Read = .false.; return
end if

read(unit=infile, fmt=*) n_file, m_file, istyle_file

if ( istyle /= istyle_file ) then
write(*,*) 'In m_read(), matrix istyle parameter does not
match file parameters.'
RM_Read = .false.; return
end if

if ( n /= n_file .or. m /= m_file) then
if ( redefine ) then
n = n_file
m = m_file
allocate(a(n,m)) !a.resize(n,m)
else
write(*,*) 'In m_read(), matrix size parameters do not
match file parameters.'
RM_Read = .false.; return
end if
end if


do j = 1, m
do i = j, n !read lower triangular portion
read(unit=infile, fmt=*) a(i,j)
end do
end do

elseif (istyle == 4) then

if (n /= m) then
write(*,*) 'Matrix not symm, so sym matrix option not
available.'
RM_Read = .false.; return
end if

read(unit=infile, fmt=*) n_file, m_file, istyle_file

if ( istyle /= istyle_file ) then
write(*,*) 'In m_read(), matrix istyle parameter does not
match file parameters.'
RM_Read = .false.; return
end if

if ( n /= n_file .or. m /= m_file) then
if ( redefine ) then
n = n_file
m = m_file
allocate(a(n,m)) !a.resize(n,m)
!a = 0.0d0
else
write(102,*) 'In m_read(), matrix size parameters do not
match file parameters.'
call flush(unit=102)
RM_Read = .false.; return
end if
end if

do j = 1, m
read(unit=infile, fmt=*) a(j:n,j) !read(unit=infile, fmt=*)
(a(i,j), i=j,n)
end do

elseif (istyle == 5) then

if (n /= m) then
write(*,*) 'Matrix not symm, so skyline option not
available.'
RM_Read = .false.; return
end if

read(unit=infile, fmt=*) n_file, m_file, istyle_file

if ( istyle /= istyle_file ) then
write(*,*) 'In m_read(), matrix istyle parameter does not
match file parameters.'
RM_Read = .false.; return
end if

if ( n /= n_file .or. m /= m_file) then
if ( redefine ) then
n = n_file
m = m_file
allocate(a(n,m)) !a.resize(n,m)
else
write(*,*) 'In m_read(), matrix size parameters do not
match file parameters.'
RM_Read = .false.; return
end if
end if

do j = 1, n !range over all columns
read(unit=infile, fmt=*) NumElem
read(unit=infile) a(j:j+NumElem-1,j) !sizeof(double)*NumElem
end do

elseif (istyle == 6) then

if (n /= m) then
write(*,*) 'Matrix not symm, so skyline option not
available.'
RM_Read = .false.; return
end if

read(unit=infile, fmt=*) n_file, m_file, istyle_file

if ( istyle /= istyle_file ) then
write(*,*) 'In m_read(), matrix istyle parameter does not
match file parameters.'
RM_Read = .false.; return
end if

if ( n /= n_file .or. m /= m_file) then
if ( redefine ) then
n = n_file
m = m_file
allocate(a(n,m)) !a.resize(n,m)
else
write(*,*) 'In m_read(), matrix size parameters do not
match file parameters.'
RM_Read = .false.; return
end if
end if

do j = 1, n !range over all columns
read(unit=infile, fmt=*) NumElem

do irow = 1, NumElem
read(unit=infile, fmt=*) a(irow+j,j)
end do
end do
end if

RM_Read = .true.

end function RM_Read

Paul van Delst

unread,
Oct 17, 2012, 4:56:17 PM10/17/12
to
I couldn't find the relevant bit in the Fortran standard, but I did find
the following in section 12.6 "Pure Procedures":

<quote>
NOTE 12.42
Variable initialization in a type-declaration-stmt or a data-stmt
implies the SAVE attribute;[....]
</quote>

So, even though you didn't write

integer, save :: n = 0

that effectively what you're getting.

cheers,

paulv
[snip]

glen herrmannsfeldt

unread,
Oct 17, 2012, 4:56:37 PM10/17/12
to
jski <john.chl...@gmail.com> wrote:
> The routine (below) prints out:

> n = 0 m = 0
> n = 537 m = 537
> n = 537 m = 537

> Neither n nor m are declared with an attribute of "save" but they keep
> their previous values? That's why I added:

> n = 0
> m = 0

(snip)

> integer :: n = 0
> integer :: m = 0

Initialization on the declaration implies SAVE.

Though the lack of SAVE doesn't mean that they won't be saved.
(But you aren't allowed to test them without either actual
or implied SAVE.)

-- glen

Steven G. Kargl

unread,
Oct 17, 2012, 4:58:55 PM10/17/12
to
On Wed, 17 Oct 2012 13:43:44 -0700, jski wrote:

> The routine (below) prints out:
>
> n = 0 m = 0
> n = 537 m = 537
> n = 537 m = 537
>
> Neither n nor m are declared with an attribute of "save" but they keep
> their previous values? That's why I added:
>
> n = 0
> m = 0
>
> Of course, it's possible I'm missing something?
>

Read your favorite reference concerning explicit
initialization.

--
steve

jski

unread,
Oct 17, 2012, 5:49:03 PM10/17/12
to
On Oct 17, 4:56 pm, glen herrmannsfeldt <g...@ugcs.caltech.edu> wrote:
So let me get this straight, if I initialize a variable (any
variable?) in a
declaration, there's an implicit SAVE in the declaration?

What's the rationale behind this? 99.99% of the time when I initialize
a variable
in a declaration, I want the initialized values to be applied every
time I
enter the routine.

---John

glen herrmannsfeldt

unread,
Oct 17, 2012, 5:54:58 PM10/17/12
to
Steven G. Kargl <s...@removetroutmask.apl.washington.edu> wrote:
> On Wed, 17 Oct 2012 13:43:44 -0700, jski wrote:


(snip)

>> Neither n nor m are declared with an attribute of "save" but they keep
>> their previous values? That's why I added:

(snip)

> Read your favorite reference concerning explicit
> initialization.

Especially for C (and maybe a few other languages) programmers, used
to initializing automatic data.

K&R C allowed initializing auto scalars, but not arrays.
Declaring them static was sometimes a workaround.
ANSI C added initialized arrays.

Note that Fortran allows variables without SAVE (explicit
or implied) to be either static or automatic.
(Though the standard might use different wording.)

-- glen

Louis Krupp

unread,
Oct 17, 2012, 6:04:02 PM10/17/12
to
That's because 99.99% of the time, you've been coding C or C++.
Fortran is different:

http://www.cs.rpi.edu/~szymansk/OOF90/bugs.html#4

Louis

glen herrmannsfeldt

unread,
Oct 17, 2012, 6:05:31 PM10/17/12
to
jski <john.chl...@gmail.com> wrote:

(snip)

> So let me get this straight, if I initialize a variable (any
> variable?) in a
> declaration, there's an implicit SAVE in the declaration?

Yes.

> What's the rationale behind this? 99.99% of the time when I initialize
> a variable
> in a declaration, I want the initialized values to be applied every
> time I enter the routine.

You could write in C or Java.

I don't know the exact reason, but do note that without SAVE the
variable may or may not be saved, though you are not allowed,
within the standard, to test for it.

Now, they could have added a DONTSAVE keyword, but they didn't,
so even with initialization you wouldn't be sure that it was
initialized each time. That would be even more useless than
giving them the SAVE attribute, so that is what they did.

-- glen

Dick Hendrickson

unread,
Oct 17, 2012, 6:16:15 PM10/17/12
to
On 10/17/12 4:49 PM, jski wrote:
> On Oct 17, 4:56 pm, glen herrmannsfeldt<g...@ugcs.caltech.edu> wrote:
>> jski<john.chludzin...@gmail.com> wrote:
>>> The routine (below) prints out:
>>> n = 0 m = 0
>>> n = 537 m = 537
>>> n = 537 m = 537
>>> Neither n nor m are declared with an attribute of "save" but they keep
>>> their previous values? That's why I added:
>>> n = 0
>>> m = 0
>>
>> (snip)
>>
>>> integer :: n = 0
>>> integer :: m = 0
>>
>> Initialization on the declaration implies SAVE.
>>
>> Though the lack of SAVE doesn't mean that they won't be saved.
>> (But you aren't allowed to test them without either actual
>> or implied SAVE.)
>>
>> -- glen
>
> So let me get this straight, if I initialize a variable (any
> variable?) in a
> declaration, there's an implicit SAVE in the declaration?
>
> What's the rationale behind this? 99.99% of the time when I initialize
> a variable

Really? You've initialized 10,000 or so variables in programs? (always
avoid hyperbole, not 1 person in a billion can get it right! ;))

> in a declaration, I want the initialized values to be applied every
> time I
> enter the routine.
>
Fortran comes with a history and in the good old days things like DATA
statements always (99.99% certainty ;) ) de facto implied that the
variable had characteristics that were identical to the SAVE attribute.
So, the various new forms of initialization mirrored that convention
and implied save.

Also, there is a trivial way to initialize a variable every time you
enter a subprogram. There's no great advantage to adding a "new"
feature that is the opposite of the essentially same feature (with a
different spelling). There are good reasons for wanting a one-shot
initialization of a variable (random number generator, line counter for
a printer, memory manager, I/O unit manager, ...).

All that said, it's been a source of confusion for years. All I can
suggest is to use "F" (which requires the redundant SAVE in a
declaration) or buy my favorite Fortran book.

Dick Hendrickson


> ---John

Dick Hendrickson

unread,
Oct 17, 2012, 6:19:57 PM10/17/12
to
On 10/17/12 3:56 PM, glen herrmannsfeldt wrote:
> jski<john.chl...@gmail.com> wrote:
>> The routine (below) prints out:
>
>> n = 0 m = 0
>> n = 537 m = 537
>> n = 537 m = 537
>
>> Neither n nor m are declared with an attribute of "save" but they keep
>> their previous values? That's why I added:
>
>> n = 0
>> m = 0
>
> (snip)
>
>> integer :: n = 0
>> integer :: m = 0
>
> Initialization on the declaration implies SAVE.
>
> Though the lack of SAVE doesn't mean that they won't be saved.

Yes it does! The lack of the SAVE attribute (it can be implied as well
as explicitly specified) means the value won't be saved. There's no
doubt about that. Saying otherwise implies (in spite of your next
sentence) that there's some way around this.

Dick Hendrickson

dpb

unread,
Oct 17, 2012, 7:51:41 PM10/17/12
to
On 10/17/2012 3:43 PM, jski wrote:
...
> Neither n nor m are declared with an attribute of "save" but they keep
> their previous values? That's why I added:
...

> logical function RM_Read( a, istyle, infile, redefine )
> real(kind=WP), allocatable, intent(out) :: a(:,:)
...
> integer :: n = 0
> integer :: m = 0
...


From the draft Standard from WG5/1839 downloadable from NAG host at

<ftp://ftp.nag.co.uk/sc22wg5/N1801-N1850/N1830.pdf>


> 5.2.3 Initialization
> 1 The appearance of initialization in an entity-decl for an entity
> without the PARAMETER attribute specifi es that the entity is a
> variable with explicit initialization. Explicit initialization
> alternatively may be specifi ed in a DATA statement unless the variable
> is of a derived type for which default initialization is specifi ed. ...
...
> 3 Explicit initialization of a variable that is not in a common block
> implies the SAVE attribute, which may be con firmed by explicit
> specifi cation.

--

James Van Buskirk

unread,
Oct 17, 2012, 7:52:33 PM10/17/12
to
"jski" <john.chl...@gmail.com> wrote in message
news:cfac7060-a0e6-4a90...@n16g2000yqi.googlegroups.com...

> On Oct 17, 4:56 pm, glen herrmannsfeldt <g...@ugcs.caltech.edu> wrote:

> > Initialization on the declaration implies SAVE.

> > Though the lack of SAVE doesn't mean that they won't be saved.
> > (But you aren't allowed to test them without either actual
> > or implied SAVE.)

You most definitely can test whether some variables have the
SAVE attribute: variables of user-defined type with default
initialization, allocatables, and variables in a recursive
procedure.

> So let me get this straight, if I initialize a variable (any
> variable?) in a
> declaration, there's an implicit SAVE in the declaration?

> What's the rationale behind this? 99.99% of the time when I initialize
> a variable
> in a declaration, I want the initialized values to be applied every
> time I
> enter the routine.

Besides just saying that that's just the way Fortran does things,
I have always thought it wierd that similar syntax in C++ invokes
the copy constructor rather than operator= .

--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end


Ian Harvey

unread,
Oct 17, 2012, 8:28:32 PM10/17/12
to
On 2012-10-18 10:52 AM, James Van Buskirk wrote:
> "jski" <john.chl...@gmail.com> wrote in message
> news:cfac7060-a0e6-4a90...@n16g2000yqi.googlegroups.com...
>
>> On Oct 17, 4:56 pm, glen herrmannsfeldt <g...@ugcs.caltech.edu> wrote:
>
>>> Initialization on the declaration implies SAVE.
>
>>> Though the lack of SAVE doesn't mean that they won't be saved.
>>> (But you aren't allowed to test them without either actual
>>> or implied SAVE.)
>
> You most definitely can test whether some variables have the
> SAVE attribute: variables of user-defined type with default
> initialization, allocatables, and variables in a recursive
> procedure.

That's true, but I think Glen's (misdirected, but others have already
chided him for that) point was that with some implementations, local
unsaved variables (in a non-recursive procedure) may appear to a
non-conforming program as if they are retaining their value.

With default initialised components and allocatables that ability to see
the underlying implementation is most likely hidden.

glen herrmannsfeldt

unread,
Oct 17, 2012, 9:12:28 PM10/17/12
to
Ian Harvey <ian_h...@bigpond.com> wrote:

(snip, I wrote)
>>>> Though the lack of SAVE doesn't mean that they won't be saved.
>>>> (But you aren't allowed to test them without either actual
>>>> or implied SAVE.)

>> You most definitely can test whether some variables have the
>> SAVE attribute: variables of user-defined type with default
>> initialization, allocatables, and variables in a recursive
>> procedure.

Yes, I didn't consider those cases, partly because those didn't
apply to the OP case, and some of which I haven't tried.

For allocatables, as far as I know you can't test the value
without allocating it. I presume you mean that you can test
for being allocated.

> That's true, but I think Glen's (misdirected, but others have already
> chided him for that) point was that with some implementations, local
> unsaved variables (in a non-recursive procedure) may appear to a
> non-conforming program as if they are retaining their value.

Yes. If you try to find out, your program is non-conforming, but
you might find that the variable was saved. Of course, it could
also have not been saved, but accidentally have the value you
expected.

> With default initialised components and allocatables that ability to see
> the underlying implementation is most likely hidden.

As I understand it, ALLOCATABLEs can have the SAVE attribute, in which
case they keep their allocation status and value on return.

I presume, then, that one without SAVE, unlike ordinary variables,
can't be saved. That is, it can't keep its allocation status and value.

Reminds me that many years ago I had a PL/I program with a CONTROLLED
variable (PL/I's version of allocatable) that I accidentally
FREEd and reALLOCATEd. For some time, it seems it was reallocated
in exactly the same place, and so kept its value. Then, with some
other change, it didn't keep the value anymore, and I had to find
out why.

I presume Fortran could do that, too. Could be surprising to someone.

-- glen

Richard Maine

unread,
Oct 17, 2012, 9:14:34 PM10/17/12
to
Dick Hendrickson <dick.hen...@att.net> wrote:

> On 10/17/12 3:56 PM, glen herrmannsfeldt wrote:

> > Though the lack of SAVE doesn't mean that they won't be saved.
>
> Yes it does! The lack of the SAVE attribute (it can be implied as well
> as explicitly specified) means the value won't be saved. There's no
> doubt about that. Saying otherwise implies (in spite of your next
> sentence) that there's some way around this.

I'm reasonably confident that Glen is, as usual, talking about
implementation details rather than the standard.

Having the SAVE attribute is something defined by the standard. If
something doesn't have the SAVE attribute, then it doesn't have the SAVE
attribute (how's that for brilliant deduction). There is no "but maybe
it does after all".

There is, however, the possibility that an implementation might
implement non-saved variables in such a way that a nonstandard program
would see that variables retained their values in the same way as saved
variables. (Except for the few edge cases where the standard actually
mandates different behavior for saved and unsaved variables; those are
mentioned elsethread).

In other words, non-saved variables might act the same way as saved
variables in most cases in some implementations. Well, no "might" about
it; that's the way some implementations do work. I suspect that
to Glen, the fact that they act the same way in some implementations
means that they are SAVEd in those implementations. I'd maintain the
distinction that they are not SAVEd - but just act that way in cases
that can only come up for nonconforming programs.

--
Richard Maine
email: last name at domain . net
domain: summer-triangle

glen herrmannsfeldt

unread,
Oct 17, 2012, 9:18:45 PM10/17/12
to
Dick Hendrickson <dick.hen...@att.net> wrote:

(snip, I wrore)

>> Initialization on the declaration implies SAVE.

>> Though the lack of SAVE doesn't mean that they won't be saved.

> Yes it does! The lack of the SAVE attribute (it can be implied as well
> as explicitly specified) means the value won't be saved. There's no
> doubt about that. Saying otherwise implies (in spite of your next
> sentence) that there's some way around this.

>> (But you aren't allowed to test them without either actual
>> or implied SAVE.)

It is my understanding that in procedures without the RECURSIVE
attribute that local variables may be statically allocated.
That is, they might keep their value between calls.

(Not counting those mentioned in other posts.)

Without the SAVE attribute, (explicit or implied) a standard conforming
program isn't allowed to test the value to see if it changed, but
a non-conforming program might find that it does have the same value
that it had previously.

For RECURSIVE, each instance has its own copy of local variables unless
they have the SAVE attribute.

-- glen

jski

unread,
Oct 17, 2012, 9:20:56 PM10/17/12
to
On Oct 17, 6:05 pm, glen herrmannsfeldt <g...@ugcs.caltech.edu> wrote:
> jski <john.chludzin...@gmail.com> wrote:
>
> (snip)
>
> > So let me get this straight, if I initialize a variable (any
> > variable?) in a
> > declaration, there's an implicit SAVE in the declaration?
>
> Yes.
>
> > What's the rationale behind this? 99.99% of the time when I initialize
> > a variable
> > in a declaration, I want the initialized values to be applied every
> > time I enter the routine.
>
> You could write in C or Java.

No thanks. Every language has warts (C++'ers revel/delight in its
warts). I would simply say that as a general design philosophy,
explicit is better than implicit.

> I don't know the exact reason, but do note that without SAVE the
> variable may or may not be saved, though you are not allowed,
> within the standard, to test for it.
>
> Now, they could have added a DONTSAVE keyword, but they didn't,
> so even with initialization you wouldn't be sure that it was
> initialized each time. That would be even more useless than
> giving them the SAVE attribute, so that is what they did.

I just wanted to make sure it wasn't something peculiar to gfortran.
I guess you're correct, I'm use to the C/C++ way of thinking.

---John

jski

unread,
Oct 17, 2012, 9:45:13 PM10/17/12
to
BTW, I remember reading an article (long ago) by Knuth in "Software:
Practice and Experience" where he states that initializing variables
in declarations is bad practice. Should have listened to Donald.

---John

glen herrmannsfeldt

unread,
Oct 17, 2012, 10:01:05 PM10/17/12
to
jski <john.chl...@gmail.com> wrote:

(snip, I wrote)
>> You could write in C or Java.

> No thanks. Every language has warts (C++'ers revel/delight in its
> warts). I would simply say that as a general design philosophy,
> explicit is better than implicit.

Java isn't so bad, though.

>> I don't know the exact reason, but do note that without SAVE the
>> variable may or may not be saved, though you are not allowed,
>> within the standard, to test for it.

>> Now, they could have added a DONTSAVE keyword, but they didn't,
>> so even with initialization you wouldn't be sure that it was
>> initialized each time. That would be even more useless than
>> giving them the SAVE attribute, so that is what they did.

> I just wanted to make sure it wasn't something peculiar to gfortran.
> I guess you're correct, I'm use to the C/C++ way of thinking.

I didn't mind so much the way it was in K&R C.

You could initialize automatic scalars, but not arrays.
Note that it has to store the initialization value somewhere, in
addition to the variable itself. In the case of a large array,
that could be expensive.

On the other hand, for a static (SAVEd) variable, there is no
extra copy (in usual implementations).

There is another reason for it. Consider the program:

real :: x(10000000)=1;
print *,x(9999)
end

Nice small program.

Now, compile it and see how big the compiled program is.

-- glen

Richard Maine

unread,
Oct 17, 2012, 10:02:49 PM10/17/12
to
jski <john.chl...@gmail.com> wrote:

> No thanks. Every language has warts (C++'ers revel/delight in its
> warts). I would simply say that as a general design philosophy,
> explicit is better than implicit.
..
> I just wanted to make sure it wasn't something peculiar to gfortran.
> I guess you're correct, I'm use to the C/C++ way of thinking.

I personally also consider the initialization-implies-save rule to be a
bit of a wart in Fortran, though it does have it's reasons. The reasons
are historical, though, so one doesn't really see them just looking at
the current state of things.

For the current state of things, mostly consider that to set something
at the beginning of a procedure, use the assignment statement. As I
think it was DIck that mentioned, the assignment statement does that
just fine and there was considered no reason to introduce new syntax to
do the same thing. I'm aware that some people have advocated for such a
new syntax, but that has not gotten enough support to happen, in my
opinion because it is just a stylistic preference, which puts it pretty
low on the priority list of things to change the language for.

For things that you want initialized once and then saved, use an
initializer and make the SAVE explicit. As for having an initializer
without an explicit SAVE, well don't do that. It just invites confusion.

If you wonder about the alluded-to historical reasons, they really go
back to Fortran 66. In Fortran 66, there was no SAVE statement. The only
standard-conforming way to make variables retain values was to put them
in COMMON and also put that COMMON in the main program (or other
suitable scope that would be active for as long as needed). But

1. That would hav ebeen a bother.

2. Pretty much nobody paid much attention to the standard in f66 days.
I'm sure there were some people who did, but they were a tiny minority.
Most people never even saw or heard of the standard and they didn't
worry about portability.

The result of 1+2 was that there was an awful lot of code that assumed
variables would retain their values between calls. That assumption was
nonstandard, but happened to work on particular machines - or even on
most machines. F77 introduced the SAVE statement, which made it much
easier to do it right, but there were still an awful lot of people who
didn't bother because the odk ways still happened to work on most
machines... and old habits are hard to break. Awfully hard. To this day,
you still find people who think that the standard actually specifies
that all variables are SAVEd. I'd have to go look for the last time I
had to correct someone on that, but I know it hasn't been long. It never
was true in terms of the standard.

So there was a lot of "f77" code that was nonstandard, but happened to
work on most systems. A very lot of code. As in probably the majority of
allegedly f77 code. I'd grant that it might possibly have not been an
absolute majority, but it was still an awful lot.

Then came f90, which essentially could not be reasonably implemented
with everything in static memory locations. Some things could still be
static, but others could not. That old nonstandard code that happened to
work on most compilers now would have started running into a lot more
compilers where it would fail.

The initialization-implies-save rule "saved" (yes, I know, groan) a lot
of those nonstandard programs by making them actually
standard-conforming in f90. So they still work - even for compilers that
tend to make many things dynamic. That rule doesn't catch all cases of
code that assumed variables values were retained, but it catches enough
of them that it was deemed worthwhile.

I personally would not have favored the rule, but then it was done
before I was on the committee anyway.

glen herrmannsfeldt

unread,
Oct 17, 2012, 10:10:50 PM10/17/12
to
Richard Maine <nos...@see.signature> wrote:
> Dick Hendrickson <dick.hen...@att.net> wrote:

>> > Though the lack of SAVE doesn't mean that they won't be saved.

(snip regarding not having the SAVE attribute)

>> Yes it does! The lack of the SAVE attribute (it can be implied as well
>> as explicitly specified) means the value won't be saved. There's no
>> doubt about that. Saying otherwise implies (in spite of your next
>> sentence) that there's some way around this.

> I'm reasonably confident that Glen is, as usual, talking about
> implementation details rather than the standard.

Yes it is an implementation detail.

> Having the SAVE attribute is something defined by the standard. If
> something doesn't have the SAVE attribute, then it doesn't have the SAVE
> attribute (how's that for brilliant deduction). There is no "but maybe
> it does after all".

> There is, however, the possibility that an implementation might
> implement non-saved variables in such a way that a nonstandard program
> would see that variables retained their values in the same way as saved
> variables. (Except for the few edge cases where the standard actually
> mandates different behavior for saved and unsaved variables; those are
> mentioned elsethread).

One might, for example, compile two programs that are the same except
that in one a variable has the SAVE attribute, and the other does not.

Even without actually testing the variable, you can see if the
compiler generates exactly the same object code.

> In other words, non-saved variables might act the same way as saved
> variables in most cases in some implementations. Well, no "might" about
> it; that's the way some implementations do work. I suspect that
> to Glen, the fact that they act the same way in some implementations
> means that they are SAVEd in those implementations. I'd maintain the
> distinction that they are not SAVEd - but just act that way in cases
> that can only come up for nonconforming programs.

Well, if you like statically allocated better than SAVEd, that
is fine with me. That is the usual CS term, though in C static has
some other meanings, too.

On the other hand, for C, C++, and Java, procedures (or methods)
are always compiled as recursive, with no attribute needed.
Data without the static attribute has to be allocated per instance.

-- glen

jski

unread,
Oct 17, 2012, 10:39:51 PM10/17/12
to
On Oct 17, 10:10 pm, glen herrmannsfeldt <g...@ugcs.caltech.edu>
wrote:
> Richard Maine <nos...@see.signature> wrote:
Richard & Glen - THANKS for the thought replies, they mean a lot.

Richard Maine

unread,
Oct 17, 2012, 11:06:29 PM10/17/12
to
glen herrmannsfeldt <g...@ugcs.caltech.edu> wrote:

> Richard Maine <nos...@see.signature> wrote:

> > In other words, non-saved variables might act the same way as saved
> > variables in most cases in some implementations.... I'd maintain the
> > distinction that they are not SAVEd - but just act that way in cases
> > that can only come up for nonconforming programs.
>
> Well, if you like statically allocated better than SAVEd, that
> is fine with me. That is the usual CS term, though in C static has
> some other meanings, too.

Yes, I like that term better. I think it is actually good that it isn't
a Fortran term. To me, that helps clarify that one is talking about the
implementation. C has all kinds of strange definitions for some terms
(as does Fortran, certainly). I find that largely irrelevant and
certainly less important than keeping the Fortran definitions straight.

michael...@compuserve.com

unread,
Oct 18, 2012, 3:23:24 AM10/18/12
to
On Thursday, October 18, 2012 12:05:32 AM UTC+2, glen herrmannsfeldt wrote:
> jski <john.chl...@gmail.com> wrote:
>
>
> Now, they could have added a DONTSAVE keyword, but they didn't,
>
Right, because X3J3 couldn't agree on the spelling :-).

Regards,

Mike Metcalf

Dick Hendrickson

unread,
Oct 18, 2012, 10:59:47 AM10/18/12
to
NO, NO, NO!!!!! You're missing the whole point of what SAVE does and
what the standard is for. Assuming you have a standard conforming
processor, SAVE guarantees that variables will maintain their values
when a subprogram exits and is re-called. The purpose of the standard
is to allow programs to be portable to different people and to different
processors. Finding tricks that work on some processors sometimes with
some compiler switches and some OS settings is a recipe for disaster.
Think about the people you work with; how will they be able to maintain
a program that relies on magic when you're on vacation?

And, finally, just to play Devil's Advocate, having the same object code
doesn't guarantee that the programs run identically. A compiler might
choose to also generate a file containing the names and attributes of
variables, etc. and put special OS trap addresses into the generated
code. Then, each time a variable is referenced or defined the OS
responds by reading the special file and decides whether or not to put
the variable into SAVEable memory or not. Probably not the most
efficient implementation; but, easily standard conforming. ;)

More to the point, a long time ago I worked on systems where stack
versus static decisions could be controlled at link/load time. It was
during a change in calling sequences and provided a bridge for people
who had real problems going to the new system. It wasn't pretty; but it
did allow the same object file to work in either mode.

Dick Hendrickson

James Van Buskirk

unread,
Oct 18, 2012, 11:16:11 AM10/18/12
to
"Dick Hendrickson" <dick.hen...@att.net> wrote in message
news:aeajr5...@mid.individual.net...

> NO, NO, NO!!!!! You're missing the whole point of what SAVE does and what
> the standard is for. Assuming you have a standard conforming processor,
> SAVE guarantees that variables will maintain their values when a
> subprogram exits and is re-called.

C:\gfortran\clf\nosave>type nosave.f90
module mod
implicit none
contains
subroutine sub(p)
integer, pointer :: p
integer, target, save :: t = 0
write(*,'(a,i0)') 'value of t = ',t
p => t
end subroutine sub
end module mod

program prog
use mod
implicit none
integer, pointer :: p
call sub(p)
p = p+1
call sub(p)
end program prog

C:\gfortran\clf\nosave>gfortran nosave.f90 -onosave

C:\gfortran\clf\nosave>nosave
value of t = 0
value of t = 1

Richard Maine

unread,
Oct 18, 2012, 11:22:06 AM10/18/12
to
I di recall that the spelling DAMN ws once suggested. :-)

Dick Hendrickson

unread,
Oct 18, 2012, 1:23:31 PM10/18/12
to
On 10/18/12 10:22 AM, Richard Maine wrote:
> <michael...@compuserve.com> wrote:
>
>> On Thursday, October 18, 2012 12:05:32 AM UTC+2, glen herrmannsfeldt wrote:
>>> jski<john.chl...@gmail.com> wrote:
>>>
>>> Now, they could have added a DONTSAVE keyword, but they didn't,
>>>
>> Right, because X3J3 couldn't agree on the spelling :-).
>
> I di recall that the spelling DAMN ws once suggested. :-)
>
PAGAN was also on the list ;)

Dick Hendrickson

John Harper

unread,
Oct 18, 2012, 4:37:46 PM10/18/12
to
That's an interesting quality-of-implementation issue. Ifort gave me a 710kb
compiled program, three other compilers gave between 40 Mb and 40.6 Mb.

--
John Harper

glen herrmannsfeldt

unread,
Oct 18, 2012, 5:12:03 PM10/18/12
to
John Harper <john....@vuw.ac.nz> wrote:

(snip, I wrote)

>> There is another reason for it. Consider the program:

>> real :: x(10000000)=1;
>> print *,x(9999)
>> end

>> Nice small program.

>> Now, compile it and see how big the compiled program is.

> That's an interesting quality-of-implementation issue. Ifort gave me a 710kb
> compiled program, three other compilers gave between 40 Mb and 40.6 Mb.

Many will compress out zeros, but not so many the ones.

(Unless the optimizer figured out that most array elements weren't
used and optimized them away. Gfortran with -O2 doesn't seem to
optimize them out.)

Some allow for a LZW based compression on the resulting
object file, which should make it nice and small.

On the other hand, an array assignment with a scalar constant should
normally not generate a large object program.

In the OS/360 days, I once punched (on actual cards) an object
program with an array initialized in a DATA statement to
zero. The OS/360 object program format doesn't compress at all.

-- glen

\"Vladimír Fuka <"name.surnameat

unread,
Oct 18, 2012, 5:59:14 PM10/18/12
to

>
> Neither n nor m are declared with an attribute of "save" but they keep
> their previous values? That's why I added:
>

>
> Of course, it's possible I'm missing something?

Sure, Initialized variables are 'save' by default. You really should
consult some book or web tutorial, these are the basics.

\"Vladimír Fuka <"name.surnameat

unread,
Oct 18, 2012, 6:01:05 PM10/18/12
to
Oops, sorry for some reason the question appeared in my reader as
unanswered and recent.

Louisa

unread,
Oct 22, 2012, 4:54:47 AM10/22/12
to
On Oct 18, 8:49 am, jski <john.chludzin...@gmail.com> wrote:

logical function RM_Read( a, istyle, infile, redefine )
real(kind=WP), allocatable, intent(out) :: a(:,:)
integer, intent(in) :: istyle
integer, intent(in) :: infile
logical, intent(in) :: redefine

integer :: n = 0
integer :: m = 0
integer :: n_file, m_file, istyle_file
integer :: i, j
integer :: irow
integer :: NumElem !no. elements written from col

write(6,*) 'n =', n, 'm =', m
call flush(unit=6)

n = 0
m = 0

if (allocated(a)) then
n = size(a, dim=1)
m = size(a, dim=2)
end if

> So let me get this straight, if I initialize a variable (any
> variable?) in a
> declaration, there's an implicit SAVE in the declaration?
>
> What's the rationale behind this? 99.99% of the time when I initialize
> a variable
> in a declaration, I want the initialized values to be applied every
> time I enter the routine.

Since that is what you want to do in this particular program,
it is better programming practice to write

if (allocated(a)) then
n = size(a, dim=1)
m = size(a, dim=2)
else
m = 0
n = 0
end if

and then it's quite clear that m and n are always initialized.
0 new messages