How do optional variables work?

I have the following program:

program hello
implicit none
integer :: a

a = 5

call print_hello()  ! Prints F
call print_hello(a)  ! Prints T
! call print_hello(something_recognized_as_not_present)  ! Prints F

contains

subroutine print_hello(some_variable)
implicit none
integer, optional :: some_variable

print *, "Hello. some_variable is present? ", present(some_variable)

end subroutine print_hello


end program hello

Is there any way to create something along the lines of something_recognized_as_not_present? My reason for wanting this is that I’m trying to expose a Fortran subroutine that has optional arguments to C, and I’d like to set it up such that when C passes nullptr for an argument, Fortran interprets that as not present. If it was only 1 optional argument I could do an if statement along with C_ASSOCIATED, but there are over 10 so when you consider all their possible combinations thats >1024 if statements :frowning:

I managed to figure something out, the following code does what I want as far as the example goes, it’s yet to be determined if this will work for my application but it looks promising:

program hello
implicit none
integer :: a
integer, pointer :: b

print *, "b is associated? ", associated(b)  ! Prints T, for some reason
b => null()
print *, "b is associated? ", associated(b)  ! Prints F

a = 5

call print_hello()  ! Prints F
call print_hello(a)  ! Prints T
call print_hello(b)  ! Prints F

contains

subroutine print_hello(some_variable)
implicit none
integer, optional :: some_variable

print *, "Hello. some_variable is present? ", present(some_variable)

end subroutine print_hello


end program hello

edit: Compiler Explorer

Since An unallocated variable passed as an argument is not PRESENT, your something_recognized_as_not_present could be an allocatable scalar that has not been allocated, as in the following code

program hello
implicit none
integer :: a
integer, allocatable :: b
a = 5
call print_hello()  ! prints "variable not present"
call print_hello(a) ! prints "variable is 5"
call print_hello(b) ! prints "variable not present"
allocate (b, source=3)
call print_hello(b) ! prints "variable is 3"
contains
subroutine print_hello(some_variable)
implicit none
integer, optional :: some_variable
if (present(some_variable)) then
   print*,"variable is", some_variable
else
   print*,"variable not present"
end if
end subroutine print_hello
end program hello

Quoting fortran: Detecting null-pointer passed as dummy argument - Stack Overflow, the reason your code in the 2nd post works is that

A nonpointer, nonallocatable, optional dummy argument will be treated as not present if associated with a disassociated pointer actual argument.

2 Likes