print vs write Fortran statements

The Fortran 2003 standard constitutes a strong foundation of “modern Fortran”. Modern Fortran (Fortran ≥ 2003) is so different in capabilities and coding style from Fortran 77 as to be a distinct, highly backward compatible language. Almost all of Fortran 95 was incorporated into Fortran 2003, except for a few obscure little used and confusing features deprecated and already unsupported by some popular compilers.

Writing to console effectively: write(*,*) grew out of non-standard use of Fortran 66’s write statement that was introduced for device-independent sequential I/O. Although write(*,*) became part of Fortran 77 for printing to console standard output, the Fortran 77 print command is more concise and more importantly visually distinct. That is, where the full versatility of the write command is not needed, print should be used to help make those cases where write is needed more distinct.

Assembly language comparison: print *,'hi' and write(*,*) 'hi' are IDENTICAL in assembly, within modern compilers as it should be. In general, disassemble Fortran executables with:

gfortran myprog.f90

objdump --disassemble a.out > myprog.s

Fortran 2003 finally settled the five-decade old ambiguity over console I/O with the intrinsic iso_fortran_env module, which is often invoked at the top of a Fortran module like:

module mymod

use, intrinsic:: iso_fortran_env, only: stdout=>output_unit, stdin=>input_unit, stderr=>error_unit

The => operators are here for renaming (they have other meanings for other Fortran statements). It’s not necessary to rename, but it’s convenient for the popularly used names for these console facilities.

Recommendation: routine console printing:

print *, 'Hello text'

For advanced console printing, whether to output errors, use non-advancing text, or toggle between log files and printing to console, use write(stdout,*) or the like.


Example: print to stdout console if output filename not specified

use, intrinsic:: iso_fortran_env, only: stdout=>output_unit

implicit none (type, external)

character(:), allocatable :: fn
integer :: i, u, L

call get_command_argument(1, length=L, status=i)
if (i /= 0) error stop "first command argument not available"
allocate(character(L) :: fn)
call get_command_argument(1, fn)
if (i==0) then
  print '(a)', 'writing to ' // fn
  open(newunit=u, file=fn, form='formatted')
else
  u = stdout
endif

i = 3 ! test data

write(u,*) i, i**2, i**3

if (u /= stdout) close(u)   ! closing stdout can disable text console output, and writes to file `fort.6` in gfortran

print *,'goodbye'

! end program implies closing all file units, but here we close in case you'd use in subprogram (procedure), where the file reference would persist.
end program

Non-advancing stdout/stdin (for interactive Fortran prompts)