The intent(out) attribute means that the value of the argument after
invoking the procedure is entirely the result of executing that procedure.
intent(in) is just literally indicating the intent of the programmer.
As has come up before, the compilers are free to try and report when an
intent(in) value has been changed, but it is hard to detect. Although
the programmer can avoid the problems this can produce by making a copy
before the call or in the called procedure that defeats the purpose
most programmers have in specifying the attribute in the first place.
Should the standard provide some alternate attribute that ensures the
value is copied if necessary so that there is a strict enforceable
meaning like with intent(out)?
I keep finding what can be a subtle bug (especially when the value is
only conditionally changed) that the longer example program illustrates,
(and at least three compilers do not seem able to detect) as an example
of a real-world mistake that I keep seeing, partly because the word
INTENT is not being taken literally; but the fact an intent(out) does
always have a predictable action really makes it non-intuitive that
intent(in) does not.
One of the strengths of the Fortran language are parts of the design specifically make it hard to make errors commonly found in codes written in other languages. It seems like it missed the mark, even though I am sure there was good intent .
program intent_out
integer,allocatable :: i(:)
if(allocated(i))deallocate(i)
allocate(i(10))
i=123
write(*,*)'I allocation before=',allocated(i)
call out(i)
write(*,*)'I allocation after=',allocated(i)
contains
subroutine out(j)
integer,allocatable,intent(out) :: j(:)
write(*,*)'J allocation=',allocated(j)
end subroutine out
end program intent_out
I allocation before= T
J allocation= F
I allocation after= F
Example code
program testit
implicit none
integer :: array(20,50)
integer :: i, x, y, c
! fill an array with blocks of integer values that are an
! ADE (ASCII decimal equivalent of a printable character (ie. 32 to 126)
array(:,:)=61 ! pre-fill array
! Fill array with rectangles of values
array( 5:15, 4:45) = 43
array( 10:12, 3:35) = 45
array( 13:18, 2:45) = 45
array( 2:10, 26:49) = 45
array( 3: 8, 30:44) = 42
array( 2: 2, 2:14) = 45
! print the array assuming the values can be printed as characters
write (*, fmt = '(50a1)') (char(array(i,:)),i=1,size(array,dim=1))
! pick a point <10,17> and flood fill starting at the point with value 35
x=10
y=17
c=array(10,17)
#ifdef ADD_BUG
! NOTE: DO NOT DO THIS INSTEAD:
write(*,*)'BAD'
call flood_fill(array,y,x,array(10,17),35)
! you would be passing in a value that will be changed during the
! recursion!
#else
write(*,*)'GOOD'
call flood_fill(array,y,x,c,35)
#endif
! print the array to show the change
write(*,'(a)')
write (*, fmt = '(50a1)') (char(array(i,:)),i=1,size(array,dim=1))
contains
recursive subroutine flood_fill(array,y,x,old_attr,new_attr)
integer :: array(:,:)
integer,intent(in) :: y, x, old_attr, new_attr
integer :: test_attribute
! Stack-based recursive flood-fill (Four-way)
test_attribute=array(y,x)
! prevent loop changing A to A Found something of the old color
if(test_attribute.ne.new_attr .and. test_attribute.eq.old_attr)then
array(y,x)=new_attr
if(x.gt.1) call flood_fill(array,y,x-1,old_attr,new_attr)
if(x.lt.size(array,dim=2))call flood_fill(array,y,x+1,old_attr,new_attr)
if(y.gt.1) call flood_fill(array,y-1,x,old_attr,new_attr)
if(y.lt.size(array,dim=1))call flood_fill(array,y+1,x,old_attr,new_attr)
endif
end subroutine flood_fill
end program testit
good output
GOOD output
GOOD
==================================================
=-------------===========------------------------=
=========================----***************-----=
=========================----***************-----=
===++++++++++++++++++++++----***************-----=
===++++++++++++++++++++++----***************-----=
===++++++++++++++++++++++----***************-----=
===++++++++++++++++++++++----***************-----=
===++++++++++++++++++++++------------------------=
==###############--------------------------------=
==#################################++++++++++=====
==#################################++++++++++=====
=############################################=====
=############################################=====
=############################################=====
=############################################=====
=#########-----------------------------------=====
=--------------------------------------------=====
==================================================
==================================================
bad output
BAD output
BAD
==================================================
=-------------===========------------------------=
=========================----***************-----=
=========================----***************-----=
===++++++++++++++++++++++----***************-----=
===++++++++++++++++++++++----***************-----=
===++++++++++++++++++++++----***************-----=
===++++++++++++++++++++++----***************-----=
===++++++++++++++++++++++------------------------=
==###############--------------------------------=
==#################################++++++++++=====
==#################################++++++++++=====
=############################################=====
=############################################=====
=############################################=====
=############################################=====
=#########-----------------------------------=====
=--------------------------------------------=====
==================================================
==================================================