Exercises: Setting Up
This is a hands-on chapter, so most of these exercises want you at a keyboard: install the compiler, type the program, compile it, run it, and — crucially — predict the output before you run it. The prediction is the exercise; the run only confirms whether you understood. Get in the habit now, on programs small enough that you can trace them completely.
Difficulty: ⭐ warm-up · ⭐⭐ standard · ⭐⭐⭐ deeper. Solutions: worked solutions to the daggered (†)
and odd-numbered problems are in appendices/answers-to-selected.md. Try every problem before you look.
Some setup exercises (2.1) have answers that depend on your machine, so the appendix gives a model response.
Part A — Warm-ups ⭐
2.1 † Run gfortran --version in a terminal and report what happens. If you get a version number,
write it down (you want 10 or newer); if you get "command not found," which section of this chapter tells
you how to fix it for your operating system?
2.2 What does the .f90 file extension tell the compiler about the form of your source? Name one
extension that would tell it the opposite.
2.3 † Name the three stages of the compile–link–run cycle, in order, and state what each stage produces or does.
2.4 In one sentence, what does implicit none do, and where in a program unit must it appear?
2.5 † What is the difference between a compiler and a linker? Give one example of a job that belongs to each.
2.6 Why does print *, "hi" produce a line that begins with a leading space, while print '(a)', "hi"
does not?
Part B — Type, Compile, and Run ⭐⭐
For each of these, write down your predicted output first, then compile with
gfortran -std=f2018 -Wall -g -fcheck=all … and run it to check yourself.
2.7 † Predict the exact output, then verify:
program greet
implicit none
print '(a)', 'line one'
print '(a)', 'line two'
end program greet
2.8 Predict the output of both print statements, paying attention to leading spaces:
program spacing
implicit none
print *, 'star form'
print '(a)', 'paren form'
end program spacing
2.9 † Predict what this prints, then verify. (The _dp reals and f0.2 format are from §2.7.)
program divide
use, intrinsic :: iso_fortran_env, only: dp => real64
implicit none
real(dp) :: result
result = 7.0_dp / 2.0_dp
print '(a, f0.2)', 'seven halves = ', result
end program divide
2.10 Modify the plate_estimate program from §2.7 so the hot edge is 80 degrees and the three cold
edges are 20 degrees. Predict the printed average by hand, then compile and run to confirm.
2.11 † (Port it.) Translate this Python snippet into a complete, compilable Fortran program that prints the same value, then compile and run both and compare:
hot = 100.0
cold = 0.0
print("range =", hot - cold)
Use real(dp) for the numbers and print '(a, f0.2)' for the output. What does yours print?
Part C — The Compile–Link–Run Cycle ⭐⭐
2.12 † What does the -c flag tell gfortran to do, and what file does it leave behind? Why can you not
run that file directly?
2.13 † You compile a program and the build fails with the message undefined reference to 'compute_flux_'.
Which stage of the cycle failed — compiling or linking? Give two plausible causes.
2.14 † † You compile a program and the build fails with Error: Symbol 'tempreature' at (1) has no
IMPLICIT type. Which stage failed, what almost certainly caused it, and what is the fix? (This one is
daggered because it is the error you will see most often as a beginner.)
2.15 In your own words, explain why the ability to compile files separately and then link them matters for a program made of two hundred source files. What would the alternative cost you every time you changed one line?
Part D — The Flags That Matter ⭐⭐
2.16 † Match each flag to what it does:
| Flag | Purpose | |
|---|---|---|
-std=f2018 |
(a) insert run-time checks such as array bounds | |
-Wall |
(b) hold the code to the 2018 ISO standard | |
-O2 |
(c) embed source-level debugging information | |
-g |
(d) enable a broad set of helpful warnings | |
-fcheck=all |
(e) optimize the generated code for speed |
2.17 † Write out the two build profiles this chapter recommends — the development profile and the
release profile — as full gfortran commands for a file sim.f90. Why does -fcheck=all belong in one
but not the other?
2.18 † A colleague benchmarks a numerical loop, compiles it with gfortran -fcheck=all sim.f90, and
reports that "Fortran is slow — this loop takes 4 seconds." What is wrong with the measurement, and what
should they do before quoting a timing?
2.19 Is a compiler warning the same as a compiler error? Does a warning stop the build? State the policy this chapter recommends for how to treat warnings, and justify it in one sentence.
Part E — Find the Bug ⭐⭐
2.20 † This program compiles and runs without complaint (there is no implicit none). What does it
print, and why is that a catastrophe rather than a convenience?
program bug1
mass = 10.0
acceleration = 9.8
frce = mass * acceleration
print *, 'force =', force
end program bug1
2.21 † What does gfortran do when it reaches the last line of this program, and why?
program mismatch
implicit none
print '(a)', 'hello'
end program goodbye
2.22 This program has implicit none and will not compile. What is the exact category of error, and
which line causes it?
program bug2
implicit none
real :: x
x = 3.0
y = x + 1.0
print '(a, f0.2)', 'y = ', y
end program bug2
2.23 † A teammate copies a block of old FORTRAN 77 into a file called old.f90 and it fails to compile
with a cascade of confusing errors. Before reading a single error message, what is your first hypothesis
about the cause, and what is the general fix?
Part F — Form and implicit none ⭐⭐⭐
2.24 † (Modernize it.) Here is a fragment in fixed-form FORTRAN 77 style. Rewrite it as a complete,
compilable, free-form modern Fortran program that does the same thing, applying the house style of this book
(lowercase keywords, implicit none, .f90, real(dp)). You do not need to preserve the uppercase or the
column layout — that is the point.
C COMPUTE THE AVERAGE OF TWO TEMPERATURES
PROGRAM AVG
A = 100.0
B = 20.0
AVERAGE = (A + B) / 2.0
PRINT *, AVERAGE
END
2.25 † The §2.6 history callout showed that in fixed-form Fortran, DO 5 I = 1.100 (with a period) is
silently read as the assignment DO5I = 1.100. Explain the two separate language features that must both
be present for this bug to slip through undetected, and state which modern feature neutralizes each one.
2.26 † Without implicit none, Fortran's implicit typing rule assigns a type to each undeclared
variable based on its first letter (i–n become integer, everything else real). Give the implicit type of
each of these names: k_max, flux, n_steps, temperature, Rho, mass.
Part G — Back of the Envelope & Build the Solver
2.27 † ⭐⭐⭐ (Back of the envelope.) Suppose that while developing your solver you rebuild and run it every time you make a change, that a full rebuild-and-run takes about 3 seconds, and that on a productive day you do this 150 times. (a) How much of your day is spent waiting for builds? (b) Now suppose the project has grown so large that a full rebuild takes 40 seconds instead of 3. How much time do you lose per day, and why does this number motivate the separate compilation of Chapter 8 (recompiling only the file you changed, then relinking)?
2.28 ⭐ (Build the solver / interleaved with Chapter 1). Complete
this chapter's Project Checkpoint: create heat-solver/heat.f90 with the banner skeleton (matching the
domain you chose back in Chapter 1 — heat, fluid, or N-body), compile it with the development profile, and
run it. Paste your compile command and the program's output as your answer, and confirm the program is named
to match the problem statement in your Chapter 1 README.md.
Coding is now the whole game. Solutions to the daggered and odd-numbered problems are in
appendices/answers-to-selected.md; the machine-dependent setup exercise (2.1) and the build exercise
(2.28) have answers that depend on your system, so the appendix gives a model response rather than a single
correct one. The worked code for the computational problems is in code/exercise-solutions.f90.