Passing arguments by pass-by-reference to a swap f

2019-09-16 04:32发布

问题:

I encountered this problem while solving a practice test

Consider the following code written in a pass-by-reference language like FORTRAN and these statements about the code

  subroutine swap(ix,iy)
    it = ix
    ix = iy    ! line L1
    iy = it    ! line L2
  end

  program main
    ia = 3
    ib = 8
    call swap (ia, ib+5)
    print *, ia, ib
  end program

Statements:

  1. The compiler will generate code to allocate a temporary nameless cell, initialize it to 13, and pass the address of the cell swap
  2. On execution the code will generate a runtime error on line L1
  3. On execution the code will generate a runtime error on line L2
  4. The program will print 13 and 8
  5. The program will print 13 and -2

Which of the above the above statement(s) is/are correct.

I think S1 and S4. Could anyone please confirm? TIA

回答1:

Yes, S1 and S4 are correct.

Also,

S0a: The file is not compilable as is because the L1: and L2: are syntax errors. :)

S0b: Strictly speaking, speaking of FORTRAN as a pass-by-reference language is incorrect:

  • The name of the language is Fortran

  • Pass by reference is an implementation detail that is not specified in the standard. Copy-in, copy-out is another possible implementation. Also, some newer Fortran language features (F90+) in practice imply an implementation which is neither pass-by-reference nor copy-in-copy-out. See e.g. pointer as a dummy argument and http://software.intel.com/en-us/blogs/2009/03/31/doctor-fortran-in-ive-come-here-for-an-argument/



回答2:

Extending the answer of @janneb... Here is a Fortran 95 syntax-correct version of the program:

module my_subs

contains

subroutine swap(ix,iy)

integer :: ix, iy
integer :: it

it = ix
ix = iy
iy = it

end subroutine swap

end module my_subs

program test_swap

use my_subs

integer :: ia, ib

ia = 3
ib = 8

call swap (ia, ib+5)

print *, ia, ib

end program test_swap

Since this is illegal, the output is not guaranteed. With gfortran and lax compiler options I get "S4", i.e., output of 13 and 8.

Now change the declaration of the arguments in the subroutine to:

integer, intent (inout) :: ix, iy

and gfortran refuses to compile it:

Error: Non-variable expression in variable definition context (actual argument to INTENT = OUT/INOUT) at (1)

Similarly for Intel ifort:

test_swap.f90(31): error #6638: An actual argument is an expression or constant; this is not valid since the associated dummy argument has the explicit INTENT(OUT) or INTENT(INOUT) attribute. call swap (ia, ib+5) -----------------^ compilation aborted for test_swap.f90 (code 1)

So with properly written code, modern Fortran compilers do not allow this. You can make this mistake if you are sloppy, and it was much easier in FORTRAN 77 and earlier.