Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29235 Discussions

internal formatted write to deferred-length allocatable character variable

Alexis_R_
New Contributor I
2,173 Views

When an allocatable deferred-length character variable has not been explicitely allocated:

  • assignment operations "automagically" allocate memory to the variable
  • but (with ifort 12)internal formatted WRITEs to this variable don't work ("output statement overflows record"), suggesting the "automagic" allocation does not occur (as in subroutine test3 in example code below).
My question:
  • is this expected behaviour for F2003 compilers?
[fortran]subroutine test1
 implicit none
 character(len=3) :: string
 real :: dummy
 !
 dummy = 3.14
 !
 write(string,'(f0.1)') dummy
 print *, string
end subroutine test1


subroutine test2
 implicit none
 character(len=:), allocatable :: string
 real :: dummy
 !
 dummy = 3.14
 allocate(character(len=3) :: string)
 !
 write(string,'(f0.1)') dummy
 print *, string
end subroutine test2

subroutine test3
 implicit none
 character(len=:), allocatable :: string
 real :: dummy
 !
 dummy = 3.14
 !
 write(string,'(f0.1)') dummy
 print *, string
end subroutine test3

program test
 implicit none
 print *, 'Running sub test1...'
 call test1()
 print *, 'Running sub test2...'
 call test2()
 print *, 'Running sub test3...'
 call test3()
end program test[/fortran]
0 Kudos
1 Solution
Ron_Green
Moderator
2,173 Views
After review, test3 is determined to be non-standard. In Fortran 2003, section 9.3, case (3) above calls it out - the record is created as the same size as the character variable passed in. It doesn't come right out and say it, but you can't pass in an undefined deferred-length character variable.

In the Fortran 2008 Standard, they added a section to prohibit what you are doing in test3:

In the F2008 standard, section "9.6.4.5.1 General" (under the sectuib Execution of a data transfer input/output statement) there is a paragraph that reads:
8 During the execution of an input statement that specifes an internal file, no part of that internal file shall be

32
defined or become undefined as the result of transferring a value to any input list item.


The phrase "no part of an internal file shall be defined ... as a result of transferring a value" indicates that automatic-allocation is not expected.

So stick with coding like test2, allocate prior to the internal write operation.

ron

View solution in original post

0 Kudos
8 Replies
Ron_Green
Moderator
2,173 Views
This is an interesting case. I've re-read section 9.3 of the F03 standard a few times ( Internal files ). It's not obvious if this is an allowed or disallowed. There is this bit:

(1) The file is a variable of default, ASCII, or ISO 10646 character type that is not an array section with a vector subscript.
(2) A record of an internal file is a scalar character variable.
(3) If the file is a scalar character variable, it consists of a single record whose length is the same as the length of the scalar character variable. ....

so in your last case, the length of the record is undefined, since the character variable has not been allocated.

BUT there is nothing that I can find that says what the behavior should be for a record of deferred-length. I did try

-assume realloc_lhs

option which has helped work around a few bugs we have had around deferred-length character variables. However, this option didn't help in this case.

let me get our Fortran standards folks to have a look at this case.

ron
0 Kudos
Ron_Green
Moderator
2,174 Views
After review, test3 is determined to be non-standard. In Fortran 2003, section 9.3, case (3) above calls it out - the record is created as the same size as the character variable passed in. It doesn't come right out and say it, but you can't pass in an undefined deferred-length character variable.

In the Fortran 2008 Standard, they added a section to prohibit what you are doing in test3:

In the F2008 standard, section "9.6.4.5.1 General" (under the sectuib Execution of a data transfer input/output statement) there is a paragraph that reads:
8 During the execution of an input statement that specifes an internal file, no part of that internal file shall be

32
defined or become undefined as the result of transferring a value to any input list item.


The phrase "no part of an internal file shall be defined ... as a result of transferring a value" indicates that automatic-allocation is not expected.

So stick with coding like test2, allocate prior to the internal write operation.

ron
0 Kudos
Alexis_R_
New Contributor I
2,173 Views
Thanks for the clarification. Disappointing, but I'm sure someone somewhere had a reason for not allowing this. Seemed to me if the automatic allocation worked for assignments, it could be made to work equally easily for internal writes. Oh well.
0 Kudos
Steven_L_Intel1
Employee
2,173 Views
It's simpler than that. The automatic [re]allocation happens only on "intrinsic assignment", not other ways the variable can take a value. The "automagic" part is described only in the section "Interpretation of intrinsic assignments." Your question is asked frequently in comp.lang.fortran and the answer is "well, that sounds like a nice idea but the standard doesn't include it". It is risky to assume that a particular behavior is more general than defined.

With my "Doctor Fortran" hat on (it has a propeller), I'll note that:

A = B

is not the same as

A(:) = B(:)

when A and B are allocatable arrays. The former gets the magic, the latter does not.
0 Kudos
Alexis_R_
New Contributor I
2,173 Views
It's simpler than that. The automatic [re]allocation happens only on "intrinsic assignment", not other ways the variable can take a value. The "automagic" part is described only in the section "Interpretation of intrinsic assignments." Your question is asked frequently in comp.lang.fortran and the answer is "well, that sounds like a nice idea but the standard doesn't include it". It is risky to assume that a particular behavior is more general than defined.

With my "Doctor Fortran" hat on (it has a propeller), I'll note that:

A = B

is not the same as

A(:) = B(:)

when A and B are allocatable arrays. The former gets the magic, the latter does not.

Thanks Steve for the further clarification. I did try to search comp.lang.fortran - sorry to ask a FAQ.

If you don't mind could you be more explicit about the difference between the A=B and A(:)=B(:) assignments? For example: Are you saying that A=B is an intrinsic assignment, but A(:)=B(:) isn't? I think I'm missing something...

0 Kudos
mecej4
Honored Contributor III
2,173 Views
The terminology and the rules governing assignment are laid out at length in Sec. 7.4 of the Fortran 2003 Standard (see link at top of this forum).
0 Kudos
Steven_L_Intel1
Employee
2,173 Views
I explained that particular item in this blog entry. Yes, that is intrinsic assignment, but that's not the only thing that matters. With A(:) on the left side, you change the destination from an "allocatable variable" to an array section, which means no reallocation.
0 Kudos
Alexis_R_
New Contributor I
2,173 Views
I explained that particular item in this blog entry. Yes, that is intrinsic assignment, but that's not the only thing that matters. With A(:) on the left side, you change the destination from an "allocatable variable" to an array section, which means no reallocation.

Thanks for clearing this up Steve.
0 Kudos
Reply