- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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]
1 Solution
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
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
Link Copied
8 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
(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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Quoting Steve Lionel (Intel)
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.
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...
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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).
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Quoting Steve Lionel (Intel)
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.

Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page