Enforce intent(in) declared variables in Fortran as constant also in called subroutines/functions

前端 未结 2 1761
渐次进展
渐次进展 2021-01-18 21:00

In a subroutine or function an input variable can be defined with intent(in) and the compiler assures that within the subroutine the variable can not be altered. As soon as

2条回答
  •  悲哀的现实
    2021-01-18 21:14

    With sufficient compiler options gfortran generates a warning for your example, that an implicit interface is used.

    If you make the interface explicit by placing the subroutines into a module, and use intents for all arguments, gfortran will catch the problem:

    module mysubs
    
    contains
    
    subroutine test(i)
        integer, intent(in) :: i
        call doSomethingNasty(i)
    end subroutine
    
    subroutine doSomethingNasty(i)
        integer, intent (inout) :: i
        i = 42 ! set the full truth ;-)
    end subroutine
    
    
    end module mysubs
    
    
    program Test_intent_in
    
    use mysubs
    
        integer i
        i = 21 ! half the truth
        call test(i)
        write (*,*) "21 expected, but is 42: ", i
    
    end program Test_intent_in
    

    gfortran gives error message:

    call doSomethingNasty(i)
                              1
    Error: Procedure argument at (1) is INTENT(IN) while interface specifies INTENT(INOUT)
    

    When pass the argument "(i)" you are passing an expression rather than a variable. The expression is not definable and thus should not be used as an actual argument for an "out" or "inout" dummy argument.

    Another approach for argument "safety": you can also use the "value" attribute in the declaration of a dummy argument to essentially make a local copy of the argument and guarantee that the actual argument won't be altered.

    Edit: As kemiisto pointed out, "contains" also makes the interface known. I don't like "contains" because the variable scoping ... all variables of the parent program are visible. Try this test code out:

    PROGRAM contains_tst
    
      INTEGER :: i, m
    
      i = 21
      m = 22
      CALL test(m)
    
      CONTAINS
    
        SUBROUTINE test(j)
          INTEGER, INTENT(IN) :: j
          write (*, *) i, j
        END SUBROUTINE test
    
    END PROGRAM contains_tst
    

提交回复
热议问题