开发者

Meaning of the INTENT of arguments/variables within subroutines and functions in Fortran 90

I have a few questions about the INTENT of variables within a subroutine in Fortran. For example, several weeks ago, I posted a question about a different Fortran topic (In Fortran 90, what is a good way to write an array to a text file, row-wise?), and one of the replies included code to define tick and tock commands. I have found these useful to time my code runs. I have pasted tick and tock below and used them in a simple example, to time a DO loop:

MODULE myintenttestsubs

  IMPLICIT NONE

CONTAINS

SUBROUTINE tick(t)
  INTEGER, INTENT(OUT) :: t
  CALL system_clock(t)
END SUBROUTINE tick

! returns time in seconds from now to time described by t
REAL FUNCTION tock(t)
  INTEGER, INTENT(IN) :: t
  INTEGER ::开发者_高级运维 now, clock_rate

  CALL system_clock(now,clock_rate)

  tock = real(now - t)/real(clock_rate)
END FUNCTION tock

END MODULE myintenttestsubs

PROGRAM myintenttest
  USE myintenttestsubs
  IMPLICIT NONE
  INTEGER :: myclock, i, j
  REAL :: mytime

  CALL tick(myclock)

  ! Print alphabet 100 times
  DO i=1,100
     DO j=97,122
        WRITE(*,"(A)",ADVANCE="NO") ACHAR(j)
     END DO
  END DO

  mytime=tock(myclock)
  PRINT *, "Finished in ", mytime, " sec"
END PROGRAM myintenttest

This leads to my first question about INTENT (my second question, below, is about subroutine or function arguments/variables whose INTENT is not explicitly specified):

  1. To start the timer, I write CALL tick(myclock), where myclock is an integer. The header of the subroutine is SUBROUTINE tick(t), so it accepts the dummy integer t as an argument. However, inside the subroutine, t is given INTENT(OUT): INTEGER, INTENT(OUT) :: t. How can this be? My naive assumption is that INTENT(OUT) means that the value of this variable may be modified and will be exported out of the subroutine--and not read in. But clearly t is being read into the subroutine; I am passing the integer myclock into the subroutine. So since t is declared as INTENT(OUT), how can it be that t seems to also be coming in?

  2. I notice that in the function tock(t), the integer variables now and clock_rate are not explicitly given INTENTs. Then, what is the scope of these variables? Are now and clock_rate only seen within the function? (Sort of like INTENT(NONE) or INTENT(LOCAL), although there is no such syntax?) And, while this is a function, does the same hold true for subroutines? Sometimes, when I am writing subroutines, I would like to declare "temporary" variables like this--variables that are only seen within the subroutine (to modify input in a step preceding the assignment of the final output, for example). Is this what the lack of a specified INTENT accomplishes?

I looked in a text (a Fortran 90 text by Hahn) and in it, he gives the following brief description of argument intent:

Argument intent. Dummy arguments may be specified with an intent attribute, i.e. whether you intend them to be used as input, or output, or both e.g.

SUBROUTINE PLUNK(X, Y, Z)
REAL, INTENT(IN) :: X
REAL, INTENT(OUT) :: Y
REAL, INTENT(INOUT) :: Z
...

If intent is IN, the dummy argument may not have its value changed inside the subprogram.

If the intent is OUT, the corresponding actual argument must be a variable. A call such as

CALL PLUNK(A, (B), C)

would generate a compiler error--(B) is an expression, not a variable.

If the intent is INOUT, the corresponding actual argument must again be a variable.

If the dummy argument has no intent, the actual argument may be a variable or an expression.

It is recommended that all dummy arguments be given an intent. In particular, all function arguments should have intent IN. Intent may also be specified in a separate statement, e.g. INTENT(INOUT) X, Y, Z.

The above text seems not even to mention argument/variable scope; it seems to be mainly talking about whether or not the argument/variable value may be changed inside the subroutine or function. Is this true, and if so, what can I assume about scope with respect to INTENT?


You're mostly right about the intent, but wrong about the semantics of tick(). The tick routine

SUBROUTINE tick(t)
  INTEGER, INTENT(OUT) :: t
  CALL system_clock(t)
END SUBROUTINE tick

does output a value; the intent, which is passed out, is the value of the system clock at the time the subroutine is called. Then tock() uses that value to calculate the time elapsed, by taking that time as an input, and comparing it to the current value of system_clock:

REAL FUNCTION tock(t)
  INTEGER, INTENT(IN) :: t
  INTEGER :: now, clock_rate

  CALL system_clock(now,clock_rate)

  tock = real(now - t)/real(clock_rate)
END FUNCTION tock

As to scope: intent(in) and intent(out) necessarily only apply to "dummy arguments", variables that are passed in the argument list of a function or subroutine. For instance, in the above examples, the variables are locally referred to as t, because that's what the corresponding dummy argument is called, but the variable necessarily has some existance outside this routine.

On the other hand, the variables now and clock_rate are local variables; they only exist in the scope of this routine. They can have no intent clauses, because they can not take values passed in nor pass values out; they exist only in the scope of this routine.


Compilers are not required to detect all mistakes by the programmer. Most compilers will detect fewer mistakes by default and become more rigorous via compilation options. With particular options a compiler is more likely to detect a violation of argument intent and output a diagnostic message. This can be helpful in more quickly detecting a bug.

The difference between declaring no intent and intent(inout) is subtle. If the dummy is intent (inout), the actual argument must be definable. One case of a non-definable argument is a constant such as "1.0". It makes no sense to assign to a constant. This can be diagnosed at compile time. If the dummy argument has no specified intent, the actual argument must be definable if it is assigned to during execution of the procedure. This is much more difficult to diagnose since it might depend on program flow (e.g., IF statements). See Fortran intent(inout) versus omitting intent


After a quick search, I found this question: What is the explicit difference between the fortran intents (in,out,inout)?

From that I learned: "Intents are just hints for the compiler, and you can throw that information away and violate it." -- from The Glazer Guy

So my guess to your first question is: the intent(OUT) assignment only tells the compiler to check that you are actually passing a variable to the tick() subroutine. If you called it like so:

call tick(10)

you'd get a compilation error. The answers to the question linked above also discusses the differences between intents.

For your second question, I think it's important to distinguish between arguments and local variables. You can assign intents to the the arguments to your subroutine. If you don't assign an intent to your arguments, then the compiler can't help you make sure you are calling the subroutines correctly. If you don't assign intents and call the subroutine incorrectly (eg the way tick() was called above), you'll get an error at run time (Segmentation Fault) or some sort of erroneous behavior.

Your subroutines can also have local variables that act as temporary variables. These variables cannot have intents. So the now and clock_rate variables in your tock subroutine are local variables and should not have intents. Try to give them intents and see what happens when you compile. The fact that they don't have intents does not mean the same thing as an argument without an intent. These two variables are local and are only known to the subroutine. Arguments without intent can still be used to pass information to/from a subroutine; there must be default intent, similar to intent(inout), but I have no documentation to prove this. If I find that, I'll edit this answer.

EDIT: Also you might want to see this page for a discussion of issues resulting from INTENT(OUT) declarations. It's an advanced scenario, but I thought it might be worth documenting.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜