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

Transmission of character string by argument

45 views
Skip to first unread message

bru

unread,
Apr 15, 2008, 3:10:49 AM4/15/08
to
Hello,

I do not understand why I have this fatal error when compiling the
following test code with NAG f95

PROGRAM TST_STRING

CALL SUBSTR('HELLO THE WETHER IS NICE')
CALL SUBSTR('HELLO THE WETHER IS ')
CALL SUBSTR('HELLO THE WETHER ')
STOP

END
SUBROUTINE SUBSTR(STRNG)
CHARACTER(24) STRNG

WRITE(6,*) 'STRING=', STRNG
RETURN

END

Error: tst_string.f: Argument STRNG (no. 1) in reference to SUBSTR from
TST_STRING is too short a character string
[f95 error termination]
ccali05{bru}54:

The number of characters is less or equal 24 !!!!!
Nevertheless it runs ok with Sun f90, f77; ifort; pgf95 pgf77 ; g95,g77
(for fortran 77 I put CHARACTER*24)

The above code works with NAG f95 if in the subroutine I put
CHARACTER(*) STRNG

Regards

B Bru

Arjen Markus

unread,
Apr 15, 2008, 3:28:17 AM4/15/08
to

That is precisely the reason: the routine is expecting
a string of exactly 24 characters and you pass a string
that is shorter. Some compilers may handle this by
converting the argument to a string of 24 characters (at least
conceptually), but NAG f95 sees it as an error.

I almost always use character(*) when passing a character
argument - that avoids this sort of thing completely!

Regards,

Arjen

Gerry Ford

unread,
Apr 15, 2008, 4:03:01 AM4/15/08
to

"Arjen Markus" <arjen....@wldelft.nl> wrote in message
news:9f5f0b9e-c20a-47e5...@b64g2000hsa.googlegroups.com...

--->Before Arjen's change, I get this from an f95 compiler:
Runtime error from program:c:\program
files\silverfrost\ftn95\freeformat7.exe
Run-time Error
*** Error 426, CHARACTER dummy argument defined to be larger than actual
argument

Arjen's version allows for a better-stated result:

PROGRAM TST_STRING

CALL SUBSTR('HELLO THE WETHER IS NICE')
CALL SUBSTR('HELLO THE WETHER IS ')

CALL SUBSTR('Whether the weather is nice is an empirical observation.
')
STOP

END
SUBROUTINE SUBSTR(STRNG)
CHARACTER(*) STRNG

WRITE(6,*) 'STRING=', STRNG
RETURN

END

--
"Shopping for toilets isn't the most fascinating way to spend a Saturday
afternoon. But it beats watching cable news."

~~ Booman


e p chandler

unread,
Apr 15, 2008, 8:19:27 AM4/15/08
to

1. Compilers and run time libraries are not required to detect this
type of argument mismatch.

With g95 I see

C:\Users\epc\temp>g95 foo.f

C:\Users\epc\temp>a
STRING=HELLO THE WETHER IS NICE
STRING=HELLO THE WETHER IS HELL
STRING=HELLO THE WETHER foo.f S

C:\Users\epc\temp>

Note that the subroutine is displaying characters that are OUT OF
BOUNDS.

2. Making the subroutine an internal subprogram is ONE WAY to force
arguments to match.

C:\Users\epc\temp>type foo1.f
PROGRAM TST_STRING

CALL SUBSTR('HELLO THE WETHER IS NICE')
CALL SUBSTR('HELLO THE WETHER IS ')
CALL SUBSTR('HELLO THE WETHER ')
STOP

CONTAINS

SUBROUTINE SUBSTR(STRNG)
CHARACTER(24) STRNG

WRITE(6,*) 'STRING=', STRNG
RETURN

END SUBROUTINE

END PROGRAM


C:\Users\epc\temp>g95 foo1.f
In file foo1.f:4

CALL SUBSTR('HELLO THE WETHER IS ')

1
Warning (135): Actual character argument at (1) is shorter in length
than the fo
rmal argument
In file foo1.f:5

CALL SUBSTR('HELLO THE WETHER ')

1
Warning (135): Actual character argument at (1) is shorter in length
than the fo
rmal argument

C:\Users\epc\temp>

3. A CHARACTER(*) argument is NOT a variable length string. It is a
fixed length string whose length is fixed by the calling routine.

- e

bru

unread,
Apr 15, 2008, 9:28:06 AM4/15/08
to
Thanks for your answer to my problem
I do not understand exactly the advantage to use an internal
subroutine? You have a warning instead of nothing when using g95?

> C:\Users\epc\temp>
>
> 3. A CHARACTER(*) argument is NOT a variable length string. It is a
> fixed length string whose length is fixed by the calling routine.

So the 3rd way is the best one?
Bernard Bru

> - e
>

e p chandler

unread,
Apr 15, 2008, 10:34:10 AM4/15/08
to
On Apr 15, 9:28 am, bru <b...@ganil.fr> wrote:
> e p chandler wrote:
> > On Apr 15, 3:10 am, bru <b...@ganil.fr> wrote:
>
> >>Hello,
>
> >>        I do not understand why I have this fatal error when compiling the
> >>following test code with NAG f95
>
> >>       PROGRAM TST_STRING
>
> >>       CALL SUBSTR('HELLO THE WETHER IS NICE')
> >>       CALL SUBSTR('HELLO THE WETHER IS ')
> >>       CALL SUBSTR('HELLO THE WETHER ')
> >>       STOP
>
> >>       END
> >>       SUBROUTINE SUBSTR(STRNG)
> >>       CHARACTER(24) STRNG
>
> >>       WRITE(6,*) 'STRING=', STRNG
> >>       RETURN
>
> >>       END

[snip]

>
> >>        The above code works with NAG f95 if in the subroutine I put
> >>CHARACTER(*) STRNG
>
> >>        Regards
>
> >>B Bru
>

> > 2. Making the subroutine an internal subprogram is ONE WAY to force

There are a number of reasons to use either internal routines or
modules. Both of these provide an explicit interface for your routines
without you having to write an interface body. An explicit interface
provides argument checking.

Fortran allows subprograms to be placed in the same file or in
different files from the main program. Since separate compilation is
allowed, there was no way, under the older Fortran standards, to
require that arguments be cross-checked.

>
> > C:\Users\epc\temp>
>
> > 3. A CHARACTER(*) argument is NOT a variable length string. It is a
> > fixed length string whose length is fixed by the calling routine.
>
>         So the 3rd way is the best one?

For a routine which prints messages, CHARACTER(*) is a good choice.
Note that the called routine can NOT modify the length of the string
passed to it as an argument.

But CHARACTER(*) is not an ARRAY, so some suggest to use

CHARACTER(len=*) instead.

program message

call print_error('divide by zero')
call print_error('discriminant is negative')

contains

subroutine print_error(s)
character(len=*) s

write(*,*) 'error: ',s
end subroutine

end program

glen herrmannsfeldt

unread,
Apr 15, 2008, 10:44:05 AM4/15/08
to
bru wrote:
(snip)

>>> CALL SUBSTR('HELLO THE WETHER ')
(snip)
>>> SUBROUTINE SUBSTR(STRNG)
>>> CHARACTER(24) STRNG

>>> WRITE(6,*) 'STRING=', STRNG

>>> Error: tst_string.f: Argument STRNG (no. 1) in reference to SUBSTR from


>>> TST_STRING is too short a character string
>>> [f95 error termination]
>>> ccali05{bru}54:

>>> The number of characters is less or equal 24 !!!!!
>>> Nevertheless it runs ok with Sun f90, f77; ifort; pgf95 pgf77
>>> ; g95,g77
>>> (for fortran 77 I put CHARACTER*24)

(snip)

>> 1. Compilers and run time libraries are not required to detect this
>> type of argument mismatch.

(snip)

>> Warning (135): Actual character argument at (1) is shorter in length

>> than the formal argument
>> In file foo1.f:5
(snip)

> I do not understand exactly the advantage to use an internal
> subroutine? You have a warning instead of nothing when using g95?

As with array bounds, it isn't usually possible to check them at
compile time, and run time checks are optional.

Note that you could have CHARACTER*24 in the subroutine, but only
reference the first few characters. Some will report a warning,
with the assumption that you only reference characters that are
actually in the actual argument. I believe it is technically
illegal, but it will work with most systems.

-- glen

Richard Maine

unread,
Apr 15, 2008, 11:41:50 AM4/15/08
to
glen herrmannsfeldt <g...@ugcs.caltech.edu> wrote:

> Note that you could have CHARACTER*24 in the subroutine, but only
> reference the first few characters. Some will report a warning,
> with the assumption that you only reference characters that are
> actually in the actual argument. I believe it is technically
> illegal, but it will work with most systems.

Some will report not just a warning, but an error. In particular, I am
confident that the reported error would still be there if only the first
few characters are referenced.

I strongly disagree with the comment about it being "technically"
illegal and the implication that it is ok to do. It is just plain
illegal. It is plausible that it might result in memory corruption from
copy-out of all 24 characters.

Just don't do this. Period. Don't try to figure out what variants you
might or might not be able to get by with in some compilers. Just don't
do it at all. As Arjen suggested, use character(*) for dummy arguments.
In my opinion, it is almost always a bad idea to use any length other
than * for a character dummy argument. Non-* lengths open possibilities
for error (which I have personally been bitten by). Compilers don't
necessarily (or even usually) catch the error, so it isn't as though
using a non-* length is good for catching the error if you intended the
length to be some particular value and accidentally got one wrong; that
can result in confusing run-time errors.

In my case, I had passed an actual argument of "AN" to a dummy
character*4 argument. I couldn't then understand why testing for
equality of the dummy argument to "AN" failed. I even printed out the
dummy argument and it looked like "AN", but wouldn't test as equal. It
turned out that the dummy argument was "AN" plus two non-printable
characters, which printed as blanks. Took me a while to debug. That was
a long time ago. I'd figure it out more quickly now, except that it
wouldn't come up now in my own code, as I always use * lengths for dummy
arguments; I have not even a single exception to that in my current
code.

The quote in my signature is relevent. I consider it to have been bad
judgement on my part to use a non-* length in the dummy argument.

--
Richard Maine | Good judgement comes from experience;
email: last name at domain . net | experience comes from bad judgement.
domain: summertriangle | -- Mark Twain

Richard Maine

unread,
Apr 15, 2008, 11:41:50 AM4/15/08
to
e p chandler <ep...@juno.com> wrote:

> But CHARACTER(*) is not an ARRAY, so some suggest to use
>
> CHARACTER(len=*) instead.

Just to elaborate on a potential wording confusion. The len= form isn't
an array either. These two forms are exactly equivalent. The only
difference is in how it looks. Presumably the suggestion is based on
some people thinking that the form without len= looks like an array.

James Van Buskirk

unread,
Apr 15, 2008, 12:02:18 PM4/15/08
to
"Richard Maine" <nos...@see.signature> wrote in message
news:1iffj75.93qwvchakv7kN%nos...@see.signature...

> Just don't do this. Period. Don't try to figure out what variants you
> might or might not be able to get by with in some compilers. Just don't
> do it at all. As Arjen suggested, use character(*) for dummy arguments.
> In my opinion, it is almost always a bad idea to use any length other
> than * for a character dummy argument. Non-* lengths open possibilities
> for error (which I have personally been bitten by). Compilers don't
> necessarily (or even usually) catch the error, so it isn't as though
> using a non-* length is good for catching the error if you intended the
> length to be some particular value and accidentally got one wrong; that
> can result in confusing run-time errors.

The above applies if the dummy argument is a scalar. If the dummy
argument is an array, the rules of sequence association give you
ways to slice and dice the actual argument creatively, or to make
new and surprising errors if it happens unintentionally. But the
rule that the sequence you get from the actual argumment must be
at least as long as the dummy argument, or the part of the dummy
argument that gets used if assumed-size, still holds.

--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end


James Van Buskirk

unread,
Apr 15, 2008, 12:04:19 PM4/15/08
to
"Richard Maine" <nos...@see.signature> wrote in message
news:1iffj1u.nx1yug11vk5x0N%nos...@see.signature...

> Just to elaborate on a potential wording confusion. The len= form isn't
> an array either. These two forms are exactly equivalent. The only
> difference is in how it looks. Presumably the suggestion is based on
> some people thinking that the form without len= looks like an array.

What I have been bitten by is thinking that the form without len=
looks like a declaration of the KIND of the character variable.

glen herrmannsfeldt

unread,
Apr 15, 2008, 12:50:43 PM4/15/08
to
Richard Maine wrote:
> glen herrmannsfeldt <g...@ugcs.caltech.edu> wrote:

>>Note that you could have CHARACTER*24 in the subroutine, but only
>>reference the first few characters. Some will report a warning,
>>with the assumption that you only reference characters that are
>>actually in the actual argument. I believe it is technically
>>illegal, but it will work with most systems.

> Some will report not just a warning, but an error. In particular, I am
> confident that the reported error would still be there if only the first
> few characters are referenced.

The OP had one that reported an error, one a warning, and one
no message at all. I do agree that it shouldn't be done, but then
why a warning?

> I strongly disagree with the comment about it being "technically"
> illegal and the implication that it is ok to do. It is just plain
> illegal. It is plausible that it might result in memory corruption from
> copy-out of all 24 characters.

> Just don't do this. Period.

I agree. I was not sure when (*) was added, and that some older
code might be left from the early days. It might be that some compilers
consider it a warning to support such defective code. Though in that
case one would use (1) instead of (24) which would not have this
problem. OK, I agree, no excuse. (But then no excuse for a
warning, either.)

-- glen

Richard Maine

unread,
Apr 15, 2008, 4:21:06 PM4/15/08
to
glen herrmannsfeldt <g...@ugcs.caltech.edu> wrote:

> I was not sure when (*) was added, and that some older
> code might be left from the early days.

It was added in f77, when character type was added to the language in
the first place. Thus, there would not be any issue with "old" code,
except insomuch as some compilers might have supported a non-standard
character type prior to f77. I understand that some compilers did
support such a character type prior to f77, but I don't know much detail
on them because I never ran into one (or if so, it was a feature that
didn't come to my attention). Although some cases existed, I don't think
a character type was particularly common in pre-f77 compilers. Any code
that used such a pre-f77 character type clearly wasn't very portable.

I don't feel like dragging out my f77 subset standard documentation. It
is possible, perhaps even likely, that the subset didn't have * length.
However, there were very few subset compilers - few enough that you have
to search pretty carefully to find any. For quite a time, I had never
heard of one, but the existence of one, perhaps two, was subsequently
pointed out to me.

Gerry Ford

unread,
Apr 16, 2008, 1:24:44 AM4/16/08
to

"James Van Buskirk" <not_...@comcast.net> wrote in message
news:mLGdnajVhIsUTJnV...@comcast.com...

I think this example makes for a good pedagogical instance for what goes
wrong with dummy versus actual arguments.

If you have a dummy character*4 argument, and you have one routine that
passes "AN" and another that passes "Anatoly", I would have thought that the
latter would be in more trouble than the former.

I've only used arrays in main, so I haven't had a chance to make this
mistake in higher dimensions yet.

Jan Vorbrüggen

unread,
Apr 16, 2008, 9:26:58 AM4/16/08
to
> I think this example makes for a good pedagogical instance for what goes
> wrong with dummy versus actual arguments.

Indeed...

> If you have a dummy character*4 argument, and you have one routine that
> passes "AN" and another that passes "Anatoly", I would have thought that the
> latter would be in more trouble than the former.

Quite to the contrary. I think of it this way: The caller (actual
argument) can always "offer" more data than the callee (dummy argument)
is expecting. That is because the callee is in the active role
processing the actual argument. If the data offered is less than what
the callee is expecting - as in the case described by Richard - you are
in trouble.

It _is_ pedagogical, is it not?

Jan

0 new messages