werrer
werrer

Reputation: 13

Passing parameters to a subroutine in Fortran

I'm trying to understand how to pass some variables with values, to a subroutine, from another subroutine.

I have the code:

program pg
call sub()
end

subroutine sub()
character :: P(12,12)
character :: D(20), N(26), userInput
integer :: A,B

A = 5
B = 2
userInput = "hello"
call test(P,D,N,userInput,A,B)

end subroutine

subroutine test(P,D,N,userInput,A,B)

end subroutine test

But that gives me a warning of:

Warning: Type mismatch in argument 'p' at (1); passed CHARACTER(1) to REAL(4)

I'm not exactly sure on how to get rid of this warning, let alone if the subroutine call is correct (syntax wise). Any help would be much appreciated.

Upvotes: 1

Views: 3455

Answers (1)

arclight
arclight

Reputation: 1608

First, why this error is happening: You have not explicitly declared any variables in subroutine test so by default, the IMPLICIT variable type rules are applied - variables starting with [A-H,O-Z] are treated as single-precision reals (REAL(4)) and the remainder (starting with [I-N]) are integers. In this case, the real arguments to test are P, D, userInput, A, and B; N is treated as an integer. Also these are all treated as scalar quantities since no dimension information is provided in test.

In subroutine sub, the variable P is declared as a 12-by-12 array of length-1 strings (single characters or CHARACTER(1)). This explains why you're getting the type mismatch error.

Advice: Read up on the IMPLICIT statement and start your code with IMPLICIT NONE, always. This forces you to declare all your variables. This slight inconvenience allows the compiler to catch typos and namespace collisions and is considered best practice. It won't solve your next problem (P, D, and N are arrays passed in as arguments to a routine which expects them to be scalars) but it will get rid of the type mismatch error.

For bonus points, look into the INTENT attribute for argument declarations. If you know that certain arguments are read-only or will only have their values set within a routine, you can declare them as INTENT(IN) or INTENT(OUT). This is an added guard against accidentally changing read-only variables or reading variables before they've been initialized.

Upvotes: 3

Related Questions