Georg Umgiesser
Georg Umgiesser

Reputation: 31

Problems dynamically allocating string in Fortran

I am trying to use a variable length string to read some data from NetCDF. In order to use the NetCDF calls I must provide a string large enough to accommodate the data. But I am running into problems.

I stripped down the problem in a weird behavior of the gfortran compiler. At least I think it is so, but maybe it is a Fortran 90 feature.

Here is the sample code:

    program test
    implicit none

    integer clen,slen
    character(len=:), allocatable :: string

    clen = 10
    allocate(character(len=clen) :: string)
    slen = len(string)

    write(6,*) 'clen,slen,dlen: ',clen,slen,len(string)
    string = ' '
    write(6,*) 'clen,slen,dlen: ',clen,slen,len(string)
    string = 'test'
    write(6,*) 'clen,slen,dlen: ',clen,slen,len(string)

    end

I would expect to get for all three write statements "10 10 10", since the string I have allocated is of size 10.

However, here is what I get:

clen,slen,dlen:           10          10          10
clen,slen,dlen:           10          10           1
clen,slen,dlen:           10          10           4

It seems as if string gets reallocated every time I assign to it. This is not the behavior I expect.

I probably use an outdated version of gfortran (GNU Fortran (Debian 4.9.2-10) 4.9.2). My question is: will this behavior go away with a newer version of the compiler, or is this a feature of Fortran 90? And if this is a feature, how can I avoid it?

Upvotes: 3

Views: 2026

Answers (1)

francescalus
francescalus

Reputation: 32366

It seems as if string gets reallocated every time I assign to it.

This is exactly the case. I'll note first that your code isn't Fortran 90 compatible: so-called deferred length character variables were introduced in Fortran 2003.

When a deferred length character variable is the subject of intrinsic assignment (which is what you have here with string=...) it takes on the length of the expression on the right-hand side. This is similar to the behaviour with allocatable arrays.

After the allocate statement string is of length 10, but come

string = ' '

the right-hand side expression is of length 1 (a single blank). This means that string is deallocated and then reallocated to this new length.

Similarly to arrays, you can retain the length of the left-hand side in an assignment by using a substring:

string(:) = ' '

Such a substring is not subject to reallocation and you'll see the usual rules of fixed-length string assignment (padding or truncation of the right-hand side).

As a final comment, this reallocation is the case for assignment. When you pass string to a NetCDF procedure which populates the string it won't do such reallocation: the NetCDF procedures will consider the dummy argument as not being of deferred length. Your tests with intrinsic assignment aren't indicative of wider behaviour.

Upvotes: 2

Related Questions