This is the mail archive of the
fortran@gcc.gnu.org
mailing list for the GNU Fortran project.
Question on allocating string arrays, primarily with a declaration where LEN=*
- From: "John S. Urban" <urbanjost at comcast dot net>
- To: <fortran at gcc dot gnu dot org>
- Date: Mon, 5 Sep 2016 19:43:45 -0400
- Subject: Question on allocating string arrays, primarily with a declaration where LEN=*
- Authentication-results: sourceware.org; auth=none
Question 1:
When compiled with gfortran 5.4.0:
$gfortran -std=f2008 -Wuninitialized aaa.f90
I get an unexpected warning that 'help_text' is used uninitilialized.
>aaa.f90:4:0:
>character(len=:),allocatable :: help_text(:)
>^
>Warning: '.help_text' is used uninitialized in this function
[-Wuninitialized]
Using the following example program:
program testit
implicit none
character(len=:),allocatable :: help_text(:)
integer :: i
help_text=[ CHARACTER(LEN=80) :: &
'defines length and size with different length expressions. Yeah!',&
' aaaaaaaaaaaaa',&
' bbbbbbbbbbbbbbbbb',&
' ddddddddddddddddddddd',&
'']
write(*,'(a)')repeat('=',len(help_text(1))) !assumed at least size one
write(*,'(a)')(trim(help_text(i)),i=1,size(help_text))
write(*,'(a)')repeat('=',len(help_text(1))) !assumed at least size one
end program testit
Is this a misleading message or am I missing something?
Question 2:
I thought (perhaps incorrectly) that everything used to initialize
an allocatable string array had to be of the same constant length
when LEN=* was used in the initialization. But when I initialize
using allocatable variables instead of getting an error it works,
but sets everthing to the length of the first expression/variable. Is
this non-standard? I can shorten the example, but you can see in the
following program (which runs) that I initialized using functions
returning different lengths and with allocatable variables of
different lengths with the -std=f2008 switch and it works (sort of -
since it does not fail I would expect the length to be the length of
the longest variable):
program rabbithole
implicit none
character(len=:),allocatable :: help_text(:)
integer :: i,j
integer :: ii
integer,allocatable :: sizes(:)
character(len=*),parameter :: pten='abcdefghij'
character(len=*),parameter :: ptwenty='abcdefghijabcdefghij'
character(len=:),allocatable :: all1,all2
character(len=10) :: cten='abcdefghij'
character(len=20) :: ctwenty='abcdefghijabcdefghij'
!---------------------------------------------------------------------------
----
write(*,*)'LEN=* WORKS IF ALL STRINGS ARE THE SAME LENGTH, LEN(), SIZE(),
ALLOCATED() OK AS EXPECTED'
all1='ABCDEFGHIJ'
all2='abcdefghijABCDEFGHIJ'
write(*,*)'ALLOCATED?',allocated(help_text)
help_text=[ CHARACTER(LEN=*) :: &
'defines length and size. All strings have to be same length ? ',&
' aaaaaaaaaaaaa ',&
' bbbbbbbbbbbbbbbbb ',&
' ddddddddddddddddddddd ',&
'1234567890123456789012345678901234567890123456789012345678901234']
if(allocated(help_text))then
write(*,*)'ALLOCATED?',allocated(help_text)
if(size(help_text).ge.1)then
write(*,*)'SIZE',size(help_text)
write(*,*)'LEN ',len(help_text(1))
else
write(*,*)'ERROR: NO SIZE'
endif
else
write(*,*)'ERROR: NOT ALLOCATED'
endif
call printit()
!---------------------------------------------------------------------------
----
write(*,*)' GET ERROR IF DIFFERENT LENGTH CONSTANT EXPRESSIONS ARE USED'
!! help_text=[ CHARACTER(LEN=*) :: '2345678901234', '12345678901234']
!! 1
!!Error: Different CHARACTER lengths (13/14) in array constructor at (1)
!!
write(*,*)' BUT OK WHEN LENGTHS ARE SAME'
help_text=[ CHARACTER(LEN=*) :: '12345678901234', '12345678901234']
call printit()
!---------------------------------------------------------------------------
----
write(*,*)'TEST NULL STRING'
help_text=[ CHARACTER(LEN=*) :: '']
call printit()
!---------------------------------------------------------------------------
----
write(*,*)'TEST STRINGS RETURNED BY FUNCTION THAT ARE THE SAME LENGTH
LEN=*'
help_text=[ CHARACTER(LEN=*) :: lenset('12345678901234567890',30),
lenset('12345678901234567890',30)]
call printit()
!---------------------------------------------------------------------------
----
write(*,*)'TEST STRINGS RETURNED BY FUNCTION THAT ARE DIFFERENT LENGTHS
LEN=*'
help_text=[ CHARACTER(LEN=*)
::lenset('12345678901234567890',10),lenset('12345678901234567890',20)]
call printit()
help_text=[ CHARACTER(LEN=*) ::
lenset('12345678901234567890',20),lenset('12345678901234567890',10)]
call printit()
write(*,*)'Appears to take length from first variable defined???. Not an
error???'
!---------------------------------------------------------------------------
----
write(*,*)'PARAMETER VERSUS VARIABLE VERSUS ALLOCATABLE LEN=*'
!! help_text=[ CHARACTER(LEN=*) :: pten, ptwenty ] ! Error: Different
CHARACTER lengths (10/20) in array constructor at (1)
!! help_text=[ CHARACTER(LEN=*) :: cten, ctwenty ] ! Error: Different
CHARACTER lengths (10/20) in array constructor at (1)
help_text=[ CHARACTER(LEN=*) :: all1, all2 ]
write(*,*)'works with allocatable, but not parameter or variable??'
call printit()
!---------------------------------------------------------------------------
----
write(*,*)'SETTING THE LENGTH WITH A CONSTANT LEN=40'
help_text=[ CHARACTER(LEN=40) :: pten, ptwenty ]
call printit()
help_text=[ CHARACTER(LEN=40) :: cten, ctwenty ]
call printit()
help_text=[ CHARACTER(LEN=40) :: all1, all2 ]
call printit()
!---------------------------------------------------------------------------
----
write(*,*)'SETTING THE LENGTH WITH A VARIABLE LEN={0,1,4,10,20,50}'
sizes=[0,1,4,10,20,50]
do j=1,size(sizes)
ii=sizes(j)
!! THIS WORKED WHEN USED CONSTANT INSTEAD OF VARIABLE?
!!help_text=[ CHARACTER(LEN=II) :: pten, ptwenty ] Error: size of
variable `A.60' is too large
!!call printit()
help_text=[ CHARACTER(LEN=II) :: cten, ctwenty ]
call printit()
help_text=[ CHARACTER(LEN=II) :: all1, all2 ]
call printit()
enddo
!---------------------------------------------------------------------------
----
write(*,*)'DOES LEN HAVE TO REDUCE TO A CONSTANT OR NOT?'
write(*,*)'ENTER LENGTH ' ! enter a negative number to be mean
read(*,*)ii
!!help_text=[ CHARACTER(LEN=II) :: pten, ptwenty ] Error: size of
variable `A.60' is too large
!!call printit()
help_text=[ CHARACTER(LEN=II) :: cten, ctwenty ]
call printit()
help_text=[ CHARACTER(LEN=II) :: all1, all2 ]
call printit()
!---------------------------------------------------------------------------
----
contains
subroutine printit()
write(*,'(a)')repeat('=',len(help_text(i)))
write(*,'(a)')(trim(help_text(i)),i=1,size(help_text))
write(*,'(a)')repeat('=',len(help_text(i)))
end subroutine printit
function lenset(line,length) result(strout) ! return string with length
LENGTH
character(len=*),intent(in) :: line
integer,intent(in) :: length
character(len=length) :: strout
strout=line
end function lenset
end program rabbithole
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!
I get different results with different compilers and the "new" features
with allocatable character arrays and initializing them with LEN=*
versus LEN=: versus no length in the declaration is a feature I have
only recently been using; but I thought the standard was that when LEN=*
was used everything in a declaration had to be of the same length and
that perhaps the length had to be a constant at compilation time; but the
test contradicts this length restriction when initializing with allocatable
expressions,
and allows lengths determined at run time (I thought I had to use LEN=: for
that). Is
this an extension/bug or allowed by the standard?
Thanks for any help clarifying this for me.