I recently happened to come across the preprocessing option most Fortran compilers support these days (as explained e.g. in the Fortran Wiki) . Coming from a C background, I would like to better understand the mechanics and caveats related to the (Fortran-)preprocessor's #include
directive.
To avoid any confusion right from the beginning: there are two include
directives in Fortran (see e.g. F77 reference)
include "foo"
is a compiler directive, i.e. foo can only contain Fortran statements#include "bar"
is a preprocessor directive, i.e. bar can contain#defines
and the like
I am aware of this difference and I am interested in the second case only (my question is therefore not a duplicate of this post).
I'll explain my questions using an example: assume we have two files, a header file (macro.h) and a source file (display.F):
macro.h
#define MSG() say_hello()
display.F
#include "macro.h"
PROGRAM display
CALL MSG()
CALL another_message()
END
SUBROUTINE say_hello()
WRITE(*,*) 'Hello.'
END
SUBROUTINE another_message()
CALL MSG()
END
Here are my questions:
Scope
where (globally, locally in the SUBROUTINE
etc.) is the macro MSG()
defined if I include macro.h:
- at the beginning of the file (as above)?
- at the beginning of the
PROGRAM display
(and nowhere else)? - at the beginning of e.g.
SUBROUTINE another_message()
(and nowhere else)?
From testing it seems: 1. globally, 2. in PROGRAM
and all SUBROUTINES
, 3. in that SUBROUTINE
only. A confirmation of these assumptions and some theoretical explanations why would be great.
What of above (1. - 3.) is best practice for preprocessor includes?
Include Guards
If I have a multi-file project and I include header.h in multiple *.F source files, do I need to provide include guards?
In case the answers to the above questions should be compiler dependent (as preprocessing is not Fortran standard), I'd be most interested in ifort's behaviour.
The rules are the same as for the C preprocessor you know. GCC even uses the same
cpp
for C and Fortran (for Fortran in the traditional mode). Therefore there is no scope around, everything is just a text and the preprocessor doesn't care about program units.Therefore, 1., 2. and 3. all are valid from the place of their definition until the file end or until
#undef
. They are also valid in recursively#include
d files.If by guards you mean
#undef
then yes, otherwise a warning or error about redefinition appears, but only if you include all those files from a single file. If they are independent then no.The key is to think about the preprocessor as a text replacement tool. It knows nothing about Fortran.
Last thing, the preprocessor is non-standard, but widely available.