0

I am trying to write a Fortran 77 program where a subroutine makes a function call, with the function being provided as an argument (to the subroutine).

The problem I am facing is that function 'bar' doesn't return the correct result. Here is a minimal (not) working example:

% cat mwe.f
      real*8 function bar()
      print *,"bar:",bar
      bar = 101.0d00
      print *,"bar:",bar
      end

      subroutine foo(func)
      real*8 rv
      rv = func()
      print *,"rv:",rv
      end

      program tsig
      external bar
      call foo(bar)
      end
% gfortran mwe.f && ./a.out
 bar:   0.0000000000000000
 bar:   101.00000000000000
 rv:   0.0000000000000000
%
3
  • Does your default real (as bar is implicitly typed in the program and foo) correspond to a declaration real*8? Commented Jan 19, 2016 at 11:56
  • Hm, as far as I can tell default real in my system is real*4. Doesn't 'real*8 function bar' make bar() return a 'real*8' ? Commented Jan 19, 2016 at 13:31
  • 1
    real*8 is the return type of bar (as declared in that function statement). However, in the main program and infoo there is no such declaration. So, func in foo is implicitly typed as default real, which may not be the same thing for you as (non-standard) real*8. Just because rv is declared as real*8 doesn't mean that the function result func() is that. Commented Jan 19, 2016 at 13:40

2 Answers 2

3

It was stated in the comments, but perhaps it should be said explicitly, because, you still appear to struggle. Keeping (pseudo) Fortran 77 you must do

  subroutine foo(func)
    real*8 rv
    real*8 func
    rv = func()
    print *,"rv:",rv
  end

The reason is that the type of func is assumed to be implicitly real inside foo. You must declare it explicitly if it returns some other type.

I strongly recommend to place implicit none at the start of each program and subroutine. It isn't part of Fortran 77 standard, but neither is real*8. Both are just common extensions. implicit none is standard in Fortran 90, real*8 is not standard Fortran at all.

Sign up to request clarification or add additional context in comments.

Comments

0

code: simple.f

function bar()
  real*8 :: bar
  print *,"bar:",bar
  bar = 101.0d00
  print *,"bar:",bar
  return
end function bar

subroutine foo(func)
    interface
      function func()
        real*8 :: func
      end function func
    end interface
    real*8 rv
    rv = func()
    print *,"rv:",rv
end subroutine foo

program tsig
  external bar
  call foo(bar)
end

result:

./a.out
 bar:   2.1219959811805460E-314
 bar:   101.00000000000000
 rv:   101.00000000000000

5 Comments

Any comments? Explanation? While this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer's long-term value.
It's also worth noting that this isn't Fortran 77. Although there are few good reasons to really write such a thing now, the question does explicitly state that requirement.
You have to add interface inside subroutine to make func visible to your calling routine. Unfortunately, It's not enough to pass it as argument.
Write it into your answer, not in the comments, which may be deleted at any time.
The code seems to work fine. Are 'interface' and :: Fortran 77 ? gfortran compiles it fine; I'm not sure how to check if Fortran 77 is assumed by default in the compiler. UPDATE: I installed 'fort77' and it can't compile this source.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.