The standard appears to state strings have to be the same length in an array constructor
unless a length type parameter is specified (NOTE 4.74). And a type-spec cannot contain
a deferred type parameter LEN=:. I thought that C418 also prohibited LEN=*, but
gfortran 5.4.0 appears to allow LEN=* as a length type parameter. Is this an extension
or standard? If standard, should the resulting length of the elements be determined by
the longest value in the array constructor or by the length of the first element or must
all values be the same length? This test program and it's output shows that in this
particular programming environment (gfortran 5.4.0) that LEN=* is allowed and that the
resulting array has elements trimmed to the length of the first element length
when the elements in the constructor are deferred length.
More specifically, can anyone clarify if the following is a standard program?
>
> character(len=:),allocatable :: textblock(:)
> ! constants of same length
> ! does LEN=* violate C418?
> textblock=[ character(len=*) :: 'abc ', '123456']
> write(*,'(a)')textblock
> end
>
> Output is:
> abc
> 123456
>
> ! is this standard?
> character(len=:),allocatable :: all1,all2
> ! deferred of different lengths in this case
> all1='ABC'
> all2='abcdefghij'
> textblock=[ character(len=*) :: all1, all2]
> write(*,'(a)')textblock
> end
>
Output is:
> abc
> ABC
References:
>
> NOTE 4.74
> An example of an array constructor that specifies a length type parameter:
>
> [ CHARACTER(LEN=7) :: 'Takata', 'Tanaka', 'Hayashi' ]
>
> In this constructor, without the type specification, it would have been necessary to specify all of the constants
> with the same character length.
>
> C418 (R420 R421 R422) A type-param-value of * shall be used only
> · to declare a dummy argument,
> · to declare a named constant,
> · in the type-spec of an ALLOCATE statement wherein each allocate-object is a dummy argument of type
> CHARACTER with an assumed character length,
> · in the type-spec or derived-type-spec of a type guard statement (8.1.9), or
> · in an external function, to declare the character length parameter of the function result.
A longer test I derived these two simple cases from follows, which may or may not raise some other questions depending on the answer for the two simple cases above. If anyone could try it with another compiler I would be curious about the results, even if that is just compiler errors. If it compiles if you enter a
negative value at the prompt does it segfault, act like LEN=0 was specified, ...?
program rabbithole
! when LEN=* Expected something like : Error: Different CHARACTER lengths (10/20) in array constructor
! or Error: length not a constant
! but this runs with
! gfortran -std=f2008 -Wall nonstd.f90
! GNU Fortran (GCC) 5.4.0
implicit none
character(len=:),allocatable :: text_block(:)
integer :: i,j
integer :: ii
integer,allocatable :: sizes(:)
character(len=:),allocatable :: all11,all22
character(len=10) :: cten='abcdefghij'
character(len=20) :: ctwenty='abcdefghijabcdefghij'
!-------------------------------------------------------------------------------
all11='
12345678901'
all22='1234567890123456789012'
!-------------------------------------------------------------------------------
write(*,'(a)') repeat("X",80)
write(*,*)'TEST STRINGS RETURNED BY FUNCTION THAT ARE THE SAME LENGTH LEN=*'
text_block=[ CHARACTER(LEN=*) :: lenset('12345678901234567890',30), lenset('12345678901234567890',30)]
call printit()
!-------------------------------------------------------------------------------
write(*,'(a)') repeat("X",80)
write(*,*)'TEST STRINGS RETURNED BY FUNCTION THAT ARE DIFFERENT LENGTHS LEN=*'
text_block=[ CHARACTER(LEN=*) :: lenset('12345678901234567890',10), lenset('12345678901234567890',20)]
call printit()
text_block=[ CHARACTER(LEN=*) :: lenset('12345678901234567890',20), lenset('12345678901234567890',10)]
call printit()
write(*,*)'Appears to take length from first variable defined???. Not an error???'
!-------------------------------------------------------------------------------
write(*,'(a)') repeat("X",80)
write(*,*)'ALLOCATABLE LEN=*'
text_block=[ CHARACTER(LEN=*) :: all11, all22 ]
call printit()
!-------------------------------------------------------------------------------
write(*,'(a)') repeat("X",80)
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)
text_block=[ character(len=ii) :: cten, ctwenty ]
call printit()
text_block=[ character(len=ii) :: all11, all22 ]
call printit()
enddo
!-------------------------------------------------------------------------------
write(*,'(a)') repeat("X",80)
write(*,*)'DOES LEN HAVE TO REDUCE TO A CONSTANT OR NOT?'
write(*,*)'DOES A NEGATIVE VALUE ACT LIKE LEN=0? (4.4.5.2-5'
! 4.4.5.2
! 5 If the character length parameter value evaluates to a negative value, the length of character entities declared is zero.
write(*,*)'ENTER LENGTH ' ! enter a negative number to be mean
read(*,*)ii
text_block=[ character(len=ii) :: cten, ctwenty ]
call printit()
text_block=[ character(len=ii) :: all11, all22 ]
call printit()
!-------------------------------------------------------------------------------
contains
subroutine printit()
write(*,'(a)')repeat('=',len(text_block(i)))
write(*,'(a)')(trim(text_block(i)),i=1,size(text_block))
write(*,'(a)')repeat('=',len(text_block(i)))
end subroutine printit
function lenset(line,length) result(strout) ! return string of specified length
character(len=*),intent(in) :: line
integer,intent(in) :: length
character(len=length) :: strout
strout=line
end function lenset
end program rabbithole
!XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
! TEST STRINGS RETURNED BY FUNCTION THAT ARE THE SAME LENGTH LEN=*
!==============================
!12345678901234567890
!12345678901234567890
!==============================
!XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
! TEST STRINGS RETURNED BY FUNCTION THAT ARE DIFFERENT LENGTHS LEN=*
!==========
!1234567890
!1234567890
!==========
!====================
!12345678901234567890
!1234567890
!====================
! Appears to take length from first variable defined???. Not an error???
!XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
! ALLOCATABLE LEN=*
!===========
!
12345678901
!
12345678901
!===========
!XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
! SETTING THE LENGTH WITH A VARIABLE LEN={0,1,4,10,20,50}
!
!
!
!
!
!
!
!
!=
!a
!a
!=
!=
!1
!1
!=
!====
!abcd
!abcd
!====
!====
!1234
!1234
!====
!==========
!abcdefghij
!abcdefghij
!==========
!==========
!1234567890
!1234567890
!==========
!====================
!abcdefghij
!abcdefghijabcdefghij
!====================
!====================
!
12345678901
!12345678901234567890
!====================
!==================================================
!abcdefghij
!abcdefghijabcdefghij
!==================================================
!==================================================
!
12345678901
!1234567890123456789012
!==================================================
!XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
! DOES LEN HAVE TO REDUCE TO A CONSTANT OR NOT?
! ENTER LENGTH
!=================================
!abcdefghij
!abcdefghijabcdefghij
!=================================
!=================================
!
12345678901
!1234567890123456789012
!=================================