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

Can "CHARACTER(LEN=*)" be used in an array constructor?

378 views
Skip to first unread message

urba...@comcast.net

unread,
Sep 6, 2016, 11:03:26 PM9/6/16
to
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
!=================================



Ian Harvey

unread,
Sep 6, 2016, 11:51:33 PM9/6/16
to
On 2016-09-07 13:03, urba...@comcast.net wrote:
> 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.

That use of LEN=* is not standard conforming - as the constraint you
mention and quote below indicates.

I expect that the lack of diagnostic is just an oversight with that
compiler, rather than a deliberate extension.

(Another compiler I tried died with an ICE, so it is a common oversight!)

The normative requirement for the items in an array constructor to have
the same corresponding length parameters, in the absence of a leading
/type-spec/, is in F2008 4.8p2, as modified by TC2.

> More specifically, can anyone clarify if the following is a standard program?

None of the programs below are conforming, because of the above.

urba...@comcast.net

unread,
Sep 7, 2016, 9:43:30 AM9/7/16
to
Thanks. I reported this for gfortran and it looks like a check is in the works already.

In support of portability I'd appreciate any other compilers to be tested/reported as well. Intuitively, and because so many interpreted languages allow such an unconstrained constructor as "ARRAY=['val1' 'another' 'stil more'] without setting specific lengths I feel it is important for the compilers to carefully check for anyone "discovering" an equivalent in Fortran (which I believe does not exist),
and trying LEN=: , LEN=* or no type-spec in an array constructor to get that behavior can feel like a reasonable expectation. In this case I was testing my reading of the standard and wasn't quite sure whether my interpretation was too restrictive or not, and the only test available is to try a compiler.

It would be nice if there were more on-line compilers available to test against as there have been a lot of relatively recent changes in compilers and supported features.

Steve Lionel

unread,
Sep 7, 2016, 11:04:35 AM9/7/16
to
On 9/6/2016 11:51 PM, Ian Harvey wrote:
> (Another compiler I tried died with an ICE, so it is a common oversight!)

Mutter...mutter...escalated as issue DPD200414173...mutter..mutter...

--
Steve Lionel
Developer Products Division
Intel Corporation
Merrimack, NH

For email address, replace "invalid" with "com"

User communities for Intel Software Development Products
http://software.intel.com/en-us/forums/
Intel Software Development Products Support
http://software.intel.com/sites/support/
My Fortran blog
http://www.intel.com/software/drfortran

Refer to http://software.intel.com/en-us/articles/optimization-notice
for more information regarding performance and optimization choices in
Intel software products.
0 new messages