What is wrong in the below code:
PROGRAM MAIN
IMPLICIT NONE
real :: a,b,c
a=1.0
b=2.0
c=3.0
print*, a
print*, b
print*, c
call mistaken(a=2.0,c=3.0)
print*, a
print*, b
print*, c
CONTAINS
subroutine mistaken(a,b,c)
real, intent(inout) ::a
real, intent(out), optional :: b
real, intent(in) :: c
a=2*c*b
if(present(b)) b=2*a
end subroutine mistaken
END PROGRAM MAIN
My best,
Umut
Here is a uses as a parameter, but in subroutine mistaken declared as
intent (in out). This should be:
a=2.0
call mistaken(a,c=3.0)
>
> print*, a
> print*, b
> print*, c
>
> CONTAINS
>
> subroutine mistaken(a,b,c)
> real, intent(inout) ::a
> real, intent(out), optional :: b
> real, intent(in) :: c
> a=2*c*b
b is an optional argument and not part of your procedure call
mistaken(a,c=3.0).
> if(present(b)) b=2*a
> end subroutine mistaken
>
>
> END PROGRAM MAIN
>
> My best,
>
> Umut
Hope, this helps, Sebastian.
> What is wrong in the below code:
Two things... at least. Perhaps a third.
1. It doesn't include an indication of why *YOU* think something is
wrong with it. When asking things like that, you should include the
symptoms that you observed - not just the code. Does the compiler fail
to compile this? If so, what error messages does it give? Does it
compile but do unexpected things when executed? If so, say what was
expected and what happened. There is certainly more data than just "code
is wrong". About the only way you could get that poor a diagnostic
message would be if you showed it to a tutor who was feeling
particularly unhelpful. You won't get that message from the computer.
(You might possibly get one even more obscure - such as "segmentation
error", but you won't get "wrong code".)
2.
> call mistaken(a=2.0,c=3.0)
...
...
> subroutine mistaken(a,b,c)
> real, intent(inout) ::a
The dummy argument "a" is intent(inout). For an intent(inout) dummy, the
actual argument has to be "defineable". That is, it has to be something
whose value is allowed to change. The "out" part implies that. The
literal constant 2.0 is not allowed to change in this way.
3. Not actually an error in your code, but something that might indicate
confusion in your understanding of it. The 3 variables "a,b,c" in the
main program seem to have no role in the code. You declare them, assign
them values, and then print them out, but they have nothing to do with
the subroutine. If you think that they have anything to do with the
arguments to the subroutine, then you are confused. They are unrelated
other than in that they have the same name. I advise against such reuse
of the same name in a context like this. It is confusing... and I'm
suspicious that it might be confusing you.
Much more could be said about point 3 here, but since you didn't provide
any information about what problem(s) you are seeing or what you are
trying to do, I don't see much point in spending more time in
elaborating on something that might not even be needed. I'm just
suspicious of confusion.
--
Richard Maine | Good judgement comes from experience;
email: last name at domain . net | experience comes from bad judgement.
domain: summertriangle | -- Mark Twain
> > call mistaken(a=2.0,c=3.0)
>
> Here is a uses as a parameter,
Please, no, don't add to a common confusion by misusing the term
"parameter" in this way. No, "a" is not a parameter. I realize that this
looks a lot like part of the syntax of a PARAMTER statement, but that's
not what it is.
(I agree with the underlying issue that you are talking about - see my
simultaneous post - just not with the terminology that you use to
describe it.)
1. Your subroutine changes the value of the variable A. It also
receives a value for A. So it must be intent INOUT. However,
call mistaken(a=2.0,c=3.0)
does NOT do what you think it does. It does NOT assign a value of 2.0
to A, then call the subroutine. It calls the routine with what is in
effect a value of 2.0.
You need to assign 2.0 to A, then call the routine with A as a regular
argument:
A=2.0
call mistaken(a,c=3.0).
2. Even with #1 taken care of, what is the value of B when there is no
argument corresponding to B? Where is the variable stored? What value
is assigned to A?
As written, the program's behavior is undefined. On my system, using
g95 under XP, it gives an access violation.
Perhaps you want something like:
if (.not. present(b)) b=1.23456
--- e
> utab <umut....@gmail.com> wrote:
>>What is wrong in the below code:
> Two things... at least. Perhaps a third.
> 1. It doesn't include an indication of why *YOU* think something is
> wrong with it. When asking things like that, you should include the
> symptoms that you observed - not just the code.
It looks to me like it might have been given as a homework or even
quiz problem, where one is supposed to explain it without running it
on a computer.
As someone else said,
call mistaken(a=2.0,c=3.0)
does not change the values of a or c, as, for
example, a C programmer might expect.
The value of 2.0 might change, though.
-- glen
> A=2.0
> call mistaken(a,c=3.0).
Perhaps the following would clarify what is happening. The above is
equivalent to
a=2.0
call mistaken(a=a,c=3.0)
In that calling sequence, the "a" on the left of the equals refers
to the dummy argument in the subroutine, and the "a" on the right
refers to the variable in the main program that was just assigned a
value of 2.0.
The other problems would still in the code (referencing the dummy
argument "b" when it is not present, etc.) even with this change.
$.02 -Ron Shepard
> Perhaps you want something like:
>
> if (.not. present(b)) b=1.23456
Um. No. That is guaranteed to be wrong. If b isn't present, then you
aren't allowed to define it. I would like to have a feature where a
non-present dummy could be used as a local variable not associated with
any actual argument. But the language doesn't have such a thing.
Code that changes the value of a simple constant used to be a rite of
passage for Fortran programmers. Can modern compilers do this, e.g.
Intel Fortran?
> Code that changes the value of a simple constant used to be a rite of
> passage for Fortran programmers. Can modern compilers do this, e.g.
> Intel Fortran?
Intel Fortran will give you a run-time error if you try to do this,
though some earlier versions did not. There is an option to pass a
writable copy of the constant instead (which is then discarded on
return).
Steve
They probably shouldn't, but many probably do. I don't have a
copy of the Intel compiler, so I can't answer specifically.
You have two recourses. If you explicitly specify INTENT, then
the compiler is required to detect and report any actual argument
that's not definable if the corresponding dummy has OUT among
its intents. Unfortunately, compilers are not required to detect
or report violations of INTENT within the called procedure
(most do). The second possibility is to declare the dummy
argument with the VALUE attribute. This causes an anonymous
temporary to be created, the value of the actual argument is
copied into that temporary, the dummy argument is associated
with the copy, and the temporary is discarded when the procedure
terminates.
The problem with the above is that they both depend on the callee
to be declared a certain way. If not, the caller can still make the
mistake. I think that an undefinable actual argument should be
passed according to the rule for VALUE attributed args regardless
of the declared attributes of the dummy. I think that should be made
the official rule in the standard. It's backward compatible (no
conforming program can rely on it not happening). And it guarantees
the problem won't occur.
--
J. Giles
"I conclude that there are two ways of constructing a software
design: One way is to make it so simple that there are obviously
no deficiencies and the other way is to make it so complicated
that there are no obvious deficiencies." -- C. A. R. Hoare
C:\Program Files\Microsoft Visual Studio 8\James\clf\steve_is_right>type
steve_i
s_right.f90
program steve_is_right
implicit none
character(80) mess
mess = 'Steve is WRONG'
read(mess,10)
write(*,10)
10 format(14HSteve is right)
end program steve_is_right
C:\Program Files\Microsoft Visual Studio 8\James\clf\steve_is_right>ifort
steve_
is_right.f90
Intel(R) Fortran Compiler for Intel(R) EM64T-based applications, Version 9.1
Build 20061104
Copyright (C) 1985-2006 Intel Corporation. All rights reserved.
Microsoft (R) Incremental Linker Version 8.00.40310.39
Copyright (C) Microsoft Corporation. All rights reserved.
-out:steve_is_right.exe
-subsystem:console
steve_is_right.obj
C:\Program Files\Microsoft Visual Studio
8\James\clf\steve_is_right>steve_is_rig
ht
Steve is WRONG
C:\Program Files\Microsoft Visual Studio
8\James\clf\steve_is_right>c:\gfortran\
win64\bin\x86_64-pc-mingw32-gfortran steve_is_right.f90 -osteve_is_right
C:\Program Files\Microsoft Visual Studio
8\James\clf\steve_is_right>steve_is_rig
ht
At line 6 of file steve_is_right.f90
Fortran runtime error: Constant string in input format
(14HSteve is right)
^
Is the ifort result due to using an earlier version, or does the
current version have this behavior, which is normal for codes with
HOLLERITH and ENCODE/DECODE?
--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end
No, that's not right. Compilers aren't required to detect
errors across a CALL when INTENT is specified. INTENT isn't
one of the things listed in 12.3.1.1 that requires an explicit
interface. The only interesting constraint under INTENT
prohibits passing an INTENT(IN) pointer to an INTENT([IN]OUT)
pointer; that's because the pointerness requires an explicit
interface, so the check is free.
INTENT is really a local documentation aid. There's a constraint
that prohibits directly modifying an INTENT(IN) dummy, but
that's easily misused/abused by passing the INTENT arguments
on to a non-conforming procedure.
Dick Hendrickson
You are right that I should have been more clear. Thanks for the
clarifications so far.
Here are my humble questions:
1.) intent in(out) arguments should always be supplied but optional
arguments may be dropped from the call, however then the subsequent
arguments should be given with the keywords for the compiler to
distinguish them. This was sth. I missed. Thas was the 1st mistake. So
the right call should be like:
aa=1.0
call mistaken(aa,c=3.0)
as some of the gentle posters suggested.
2.) I was playing with this code actually to see what will change and
see some possible error conditions and learn from them. The actual
question was "find the error in the subroutine below"
subroutine mistaken(a,b,c)
real, intent(inout) ::a
real, intent(out), optional :: b
real, intent(in) :: c
a=2*c*b
if(present(b)) b=2*a
end subroutine mistaken
The whole given part of the code was the above, and after some
checking(I was on the train when I first checked this), if b is
dropped, the problem would be, I guess, is that optional argument is
undefined so that
a=2*c*b
is not defined. Is this the actual error. At least, I think in this
way.
Rgds
> 1.) intent in(out) arguments should always be supplied
That's not so. Intent is orthogonal to optionality. Having an optional
intent(inout) argument is fine.
> subroutine mistaken(a,b,c)
> real, intent(inout) ::a
> real, intent(out), optional :: b
> real, intent(in) :: c
> a=2*c*b
> if(present(b)) b=2*a
> end subroutine mistaken
>
> The whole given part of the code was the above, and after some
> checking(I was on the train when I first checked this), if b is
> dropped, the problem would be, I guess, is that optional argument is
> undefined so that
>
> a=2*c*b
>
> is not defined. Is this the actual error. At least, I think in this
> way.
Yes, this is an "error" in the subroutine (in addition to the errors
noted in calling it). To be quite pedantic, the subroutine isn't
technically necessarily erroneous. It is an error to call this
subroutine with b not present, for the reason you mention. But since it
is possible to include this subroutine in a valid program, the
subroutine is not technically invalid by itself. When you put it
together with a main program that calls it with b omitted, then that
combination is invalid.
One might consider it "silly" to have a subroutine where an argument is
declared optional, but can never be validly omitted. But the standard
doesn't prohibit such "silly" things; there are even times when they
make sense. Examples of simillarly "silly" things include
x = 1.0 !-- This value never gets used.
x = 2.0
and
if (.false.) then
...
end if
I have seen both constructs in real code and in contexts where there use
was at least somewhat sensible.
Thanks for the correction - and for reading my mind! Had I not posted
in haste, I would have assigned either a set value or the value of b
(if present) to a local variable. :-(.
-- e