A Comparison of C++, FORTRAN 90 and
Oberon-2 for Scientific Programming
CH-8307 Effretikon, Switzerland
May 12, 1995
In the past decade, the programming languages C++, FORTRAN 90 and Oberon-2 all
evolved from their ancestors. This invites to reflect upon the suitability of
these modern programming languages for scientific and engineering computing. In
the first part, we compare their primary language features, as needed by
scientists and engineers. In the second part, we list some useful features
missing in Oberon-2. The report concludes by a personal assessment of the three
languages with respect to the numerical context. The reader's experience in
scientific programming in C or FORTRAN would be advantageous.
Business computing holds the major share of the computer market. Here COBOL,
PL/1 and C have been the languages of choice, but C slowly supersedes its
competitors in recent software projects.
Scientific computing holds a minor market share. FORTRAN 77 dominated
programming in science and engineering in the past. The importance of C
increases in all programming fields, especially in science and engineering.
Data have been the primary valuables of business computing, while programs have
been the primary valuables of scientific computing. Hence, switching from
FORTRAN environments to C or Oberon is generally more laborious than switching
from COBOL environments to C or Oberon.
The small remainder of the market is shared by dedicated applications, as
system software, for example. Oberon [6, 9] evolved from Modula-2
. Oberon-2 [7, 8, 19] has been and will be a valuable
alternative to C++ [1, 2] in any context, where general-purpose
programming languages are appropriate [10, 11]. We compare Oberon-2 only
to C++ and FORTRAN 90 [3, 4], since these programming languages are
extensions of their wide-spread ancestors C and FORTRAN 77. In the following, a
familiarity with these languages is expected.
We compare only the main language features being of interest in a scientific
and engineering context [12, 13, 14,
15, 16, 17, 18]. Object-oriented
features are not discussed (see [19, 20, 21, 22]).
2.1 Identifiers and Reserved Words
Identifiers consist of a sequence of uppercase and lowercase letters,
underscore characters and digits with leading letter.
C++: Reserved words consist of lowercase letters.
FORTRAN 90: Any identifiers up to 31 characters. Pitfall: reserved words may
be valid identifiers.
Oberon-2: No underscore characters allowed. Reserved words consist of uppercase letters.
After more than three decades, FORTRAN 90 offers the record type. While some
language designers luckily leave out packed records (used in Pascal), C++
and Modula-2 allow variant records that are unsafe or inefficient
(run-time checking of the variant).
C++: Variant records, initialisation aggregates.
FORTRAN 90: Records and initialisation aggregates. The sequence statement
forces record fields to be stored in order of definition.
Oberon-2: Exported record types may have public fields (visible outside
the module) and private fields. Record types may be extensions of another
record type. No initialisation aggregates available.
2.3 Multidimensional Arrays
It should be possible to create multidimensional arrays at run-time. The static
memory management of FORTRAN 77 caused long parameter lists of procedures. The
local temporary arrays (workspace ) and array dimension had to be passed
as parameters. The creation of global and local multidimensional arrays (with
possibly no elements) at run-time, allows safe array handling and readable
source code. The restriction to 7 dimensions in FORTRAN does not harm.
C++: Static multidimensional arrays, dynamic one-dimensional arrays. Lower
index bounds are always zero.
FORTRAN 90: Static and dynamic multidimensional arrays up to 7 dimensions. Index
bounds may be declared. Lower index bounds of arrays in parameter lists of
procedures may be declared.
Oberon-2: Dynamic multidimensional arrays. Lower index bounds are always zero.
2.4 Use of Uninitialised Variables
Using uninitialised non-pointer variables invalidates the program run (wrong
data, number overflow, array index error, etc.), but processing invalid
pointers or procedure variables may crash the run-time system. The latter is
more harmful than the former.
FORTRAN 90: Possible.
Oberon-2: Possible. Local pointers may be initialised to NIL automatically,
global pointers are always initialised to NIL.
2.5 Pointer Manipulation
Low-level pointer manipulation should be restricted to modules close to
hardware as device drivers, for example. Pointer manipulation is often
responsible for software flaws and prevents portability.
C++: Abuse is easy, even constants or stack objects could be defected.
FORTRAN 90: None.
Oberon-2: Only by explicit type cast.
2.6 Dangling References
Dynamic data structures and abstract data types are usually implemented through
pointers. When explicit deallocation of objects is possible, unintentional
dereferencing of dangling pointers leads to system corruption, which is
hard to debug.
FORTRAN 90: Possible.
Oberon-2: Safe, because no explicit freeing of objects (garbage collection frees objects).
2.7 Logical Objects and Operators
Logical objects and operators are part of conditional statements anyway. The
integers zero and one are no adequate substitutes for logical values
false and true , they rather confuse the programmer. The rather simple
C++ statement "if(a=b && c+d<e)f" is legal.
C++: No logical objects but bitwise operations on characters,
enumerations, integers and bit fields. Conditions return integer values.
FORTRAN 90: Type LOGICAL with operators.
Oberon-2: Type BOOLEAN with operators.
2.8 Set Objects and Operators
Bit sets need less storage and operations are faster, compared to arrays of
logical values. In some application fields, restricting to bit sets is not
C++: Set operations on integers, bit access by masking.
FORTRAN 90: Set and bit operations on integers.
Oberon-2: Set and bit operations on bit sets.
Beneath simple comparison operators, relations of structured types should be
possible. Relation overloading is necessary for abstract data types.
C++: Relations apply to characters, enumerations, numeric and pointer types.
Warning: "a<b<c" means "(a<b)<c" and not "(a<b) and (b<c)".
FORTRAN 90: Relations apply to strings and numeric types except complex types,
equality applies to complex types.
Oberon-2: Relations apply to numeric types, characters and strings, equality
also applies to logical, set, pointer and procedure types.
2.10 Arithmetic Operators
The numerous numeric types are rather hindering than a benefit. The unsigned
integers in C++ (and Modula-2) have been primarily used for address arithmetic.
The type COMPLEX of FORTRAN could be implemented by structured function
results and operator overloading. The subtypes in FORTRAN 90 causes even more
problems. Mixing different numeric types in expressions leads to conversion
problems. It is tricky to manage operator overloading and automatic type
coercion simultaneously. It is quite stupendous that none of these programming
languages supports fixed point numbers for business computing. The number of
decimal digits in 32-bit integers and 32-bit reals are by far too small. In
general, the definition of numeric types (no minimum range!) and operators
should be more precise and portable.
C++: +,- apply to characters, enumerations, numeric and pointer types.
*,/ apply to characters, enumerations and numeric types. % (remainder )
applies to characters, enumerations and types where x = (x/y)*y + (x%y)
holds, but for xɘ or yɘ the sign of the remainder is implementation
dependent  ! No complex type.
FORTRAN 90: +,-,*,/,** (exponentiation, a**b**c = a**(b**c) but
2**(-3) truncates to zero) apply to integer, real and complex types.
Fractions of integers are truncated towards zero.
Oberon-2: +,-,*,/ (/ with real result), DIV (integers only, round to
- infinity), MOD (integers only, modulus ) where x = (x DIV y)*y + (x
MOD y), 0<=(x MOD y)<y holds. Numeric types are coerced automatically
according to the so-called type inclusion : SHORTINT <= INTEGER
<= LONGINT <= REAL <= LONGREAL. No complex type.
2.11 Go-to Statement
The lack of well-structured control statements in older programming languages
lead to excessive use of the harmful go-to statement. Maintaining so-called
spaghetti code is expensive.
C++: Unconditional go-to, return statement in procedures, break statement in
iterations and switch (case) statements.
FORTRAN 90: Unconditional go-to, arithmetic if (a conditional jump), computed
go-to (a case statement), assigned go-to (a jump to label variable). Return
statement in procedures.
Oberon-2: No explicit go-to, but return and exit statements in procedures and loops.
2.12 Procedures and Parameters
C++: Types and number of parameters are checked except for special procedures
(as printf ), where the number of parameters is unspecified. Optional
parameters are possible. Parameter passing: call by value (modify local copy),
call by reference (modify original), and call by reference with prefix const
(read-only). Arrays can not be passed by value. The number of array elements must be passed separately.
Procedure variables are pointers to functions.
FORTRAN 90: Types and number of parameters are checked. Optional parameters
are possible. Parameter passing: call by value or call by reference (compiler
decision)! The programmer may assign attributes to parameters: in for
read-only parameters, out for returned, and inout for modified
parameters. The number of array elements may be passed separately (
assumed-shape array, automatic array ). Procedure variables must be external or
Oberon-2: Types and number of parameters are checked. Parameter passing: call by
value and call by reference. Procedure variables can not be predefined procedures.
2.13 Recursive Procedure Calls
Calling procedures recursively allows adequate programming of numerous
algorithms based on divide and conquer.
FORTRAN 90: Possible when procedure marked as recursive.
2.14 Overloading of Procedures and Operators
Procedure and operator overloading supports implementation of libraries.
Operator precedence and associativity is important. Overloading of predefined
procedures and operators should be possible.
C++: Overloading of procedures and operators, definition of new operators.
FORTRAN 90: Overloading of procedures and operators, definition of new
2.15 Exception and Error Handling
An error handling by the programmer enables handling of exceptions or errors
within libraries. Preventing some errors is often less efficient and more
complicated than handling exceptions, as numeric overflow, for example.
C++: By exception handler.
FORTRAN 90: None.
2.16 Language Support for Parallelism
Parallelism is needed to solve large and time-consuming problems in science,
engineering and business. Actually, the oldest languages are used to program
supercomputers. Parallelism should be supported by modern general-purpose
FORTRAN 90: No explicit parallelism, but implicit parallelism in array
2.17 Programs and Compilation Units
A program consists of several compilation units , each encapsulating
data declarations and code. Compilation units are compiled and stored
separately. The compilation unit interface controls access to dedicated
local objects. Interface consistency means that the interface is consistent with
client and server.
C++: Files are compilation units. Interface objects are declared in so-called
header files . Interface consistency is not checked.
FORTRAN 90: A program consists of one compilation unit (main program ) and
optional compilation units (modules, external functions and procedures). The
object attributes private and public in modules control the access
of clients. Interface consistency is not checked, but user may copy the
interface into compilation unit as so-called interface block , which is
Oberon-2: Modules are compilation units. Interface objects are marked in the
source. Read-or-modify control for exported variables is available. Interface
consistency is checked.
3 Features Missing in Oberon-2
Oberon-2 needs additional features to enlarge the field of application. Some of
the features described subsequently are new, while some fit well in the present
language definition [8, 19]. Features of minor importance,
as exception handling, are not listed. The first four features primarily improve readability
and flexibility. Library programmers will benefit most. The last feature,
parallelism, is mandatory for future languages, since parallel computing will
soon be available on workstations and personal computers. At present, parallel
systems are mainly programmed in FORTRAN and C (with hardware-dependent
language extensions). If Oberon will not offer parallelism soon, it will hardly
be possible to compete with future C++ and FORTRAN 90 environments.
The array features are important for porting the FORTRAN libraries to Oberon-2.
In Oberon-2, constant arrays are missing. For initialisation of arrays,
see aggregation. FORTRAN 90 has a different storage representation of arrays
(column-by-column) than C++ and Oberon-2 (row-by-row). This impedes calling of
FORTRAN libraries by C++ or Oberon-2 programs. The different lower array
bounds are a severe obstacle for porting FORTRAN software to C++ and Oberon-2.
3.2 Arbitrary Function Result Types
Actually, the result type of a procedure can be neither a record nor an array.
Arbitrary types as function results allows more compact and readable source
code. Combined with overloaded operators, the language permits orthogonal
extensions of expressions. The type COMPLEX should be offered by a portable
library module, and not by the compiler (as FORTRAN does). The compiler
complexity will be reduced. The flexibility will be enhanced. See also
aggregation and operators.
The language is more orthogonal, readable and flexible when some operators may
be overloaded. Abstract mathematical data types (complex numbers, matrices,
polynomials etc.) will be easier to implement. This supports sophisticated
programming, as used in mathematical expert systems or software libraries.
There may be some pitfalls when using numeric type hierarchy and automatic type
extension in mixed mode. It is advantageous to merge the numeric type hierarchy
in the operator concept. Arbitrary operator definitions, as in PROLOG, should
be omitted for simplicity.
Aggregates lightens the initialisation of structured types (records, arrays,
etc.) in definitions and assignments. This is cumbersome and error-prone when
programmed explicitly. The code will be more efficient and more readable.
This feature is most ambitious . Some challenging problems (weather
forecast, fluid dynamics, molecular design etc.) are very time-consuming. They
require the computing power of parallel systems, since the hardware development
of sequential computers (temporarily) reaches physical or commercial limits.
Hence, Oberon-2 should offer parallelism to tackle this performance problem. In
addition to efficiency, parallelism is a valuable structuring tool. An Oberon
extension for vector computers is described in . The programming of
sequential computers would benefit too.
We compile a comparative overview of the language features. The marks mean:
-- no support, - poor, + average, ++ good support. Most motives for the
ranking are discussed in the first part of this paper.
|the language is easy to learn, easy to use ||-- ||-- ||++|
|one language construct per features only ||- ||-- ||+ |
|are numeric libraries for the language available ||- ||++ ||--|
|object-oriented features ||+ ||- ||+ |
|exception and error handling ||- ||-- ||--|
|support for parallelism ||-- ||- ||--|
|block-structured features ||- ||-- ||+ |
|go-to like statements avoided ||- ||-- ||+ |
|variable initialisation in definition ||++ ||+ ||--|
|logical and set types ||- ||- ||++|
|type complex ||-- ||++ ||--|
|record extension/variants ||+ ||- ||++|
|initialisation aggregates for records ||+ ||+ ||--|
|safe multidimensional arrays ||-- ||+ ||++|
|user defined lower index bound ||-- ||++ ||--|
|safe pointer handling ||-- ||++ ||+ |
|forced pointer initialisation ||-- ||-- ||+ |
|omit dangling references ||-- ||-- ||++|
|all types as procedure parameters ||- ||- ||+ |
|call by value of procedure parameters ||- ||+ ||++|
|call by reference of procedure parameters ||+ ||+ ||++|
|arbitrary function result types ||+ ||+ ||+ |
|procedure and operator overloading ||++ ||++ ||--|
|procedure recursion available ||+ ||++ ||+ |
|safe module and interface ||-- ||- ||++|
After three decades, the FORTRAN language became a partly useful patchwork of
numerous features, reflecting the history of software techniques. Actually, too
many constructs cover the same features with different side-effects and
restrictions. This aggravates software development, and is of no benefit at
all. The dusty decks will keep dusty.
In the chapter "design notes" , the author writes, "Simplicity was an
important design criterion for C++ ..."! But the language reference chapter for
C++ covers about 150 pages, versus less than 30 pages for Oberon  or
Oberon-2 . A tool should support the solving of problems, not create
problems. The originally hardware-oriented design lacks a sound programmer-oriented model. C++
offers too many concepts. Their interaction is error-prone.
We listed some features to be included in Oberon-2. Applications written in
this value-added Oberon-2 will be safer and more readable. At present,
Oberon-2 implementations are not less efficient than C++ implementations at
all. The language is easier to learn than FORTRAN 90 and C++; compare the size
of their reports;  680 pages,  740 pages, and  16
pages. The small number of language constructs facilitates a correct compiler
implementation. The programmer easily understands and memorises the
interference of Oberon-2 constructs, which is hardly possible for FORTRAN 90 and C++.
At present, the old-fashioned but value-added FORTRAN 90 seems to be inevitable
for scientific and engineering work, when one of the numerous FORTRAN libraries
When starting from scratch, or when the necessary numerical libraries are
available, Oberon-2 competes with FORTRAN 90 and C++ at ease. We prefer using
an improved Oberon-2 to master complex systems, for not being mastered by
complex systems written in FORTRAN or C.
The author would like to thank the referees for helpful suggestions, and Jörg
Waldvogel, Seminar for Applied Mathematics ETH Zürich, for carefully reading this paper.
 B. Stroustrup: The C++ Programming Language, Addison-Wesley, 1993.
 B. Stroustrup: The Design and Evolution of C++, Addison-Wesley, 1994.
 J.C. Adams, W.S. Brainerd, J.T. Martin, B.T. Smith, J.L. Wagener:
Fortran 90 Handbook. Complete ANSI/ISO Reference, McGraw-Hill, 1992.
 M. Metcalf, J. Reid: Fortran 90 Explained, Oxford University Press, 1990.
 N. Wirth: From Modula to Oberon, Dept. Informatik, Report 143, ETH Zürich, 1990.
 N. Wirth: The Programming Language Oberon, Dept. Informatik, Report 143, ETH Zürich, 1990.
 H. Mössenböck, N. Wirth: Differences between Oberon and
Oberon-2, Structured Programming, Vol. 12 Iss. 4 p. 175-177, 1991.
 H. Mössenböck, N. Wirth: The Programming Language
Oberon-2, Structured Programming, Vol. 12 Iss. 4 p. 179-195, 1991.
 M. Reiser, N. Wirth: Programming in Oberon. Steps beyond Pascal and Modula, Addison-Wesley, 1992.
 M. Reiser: The Oberon System. User Guide and Programmer's Manual, Addison-Wesley, 1991.
 J. Gutknecht, N. Wirth: Project Oberon. The Design of an
Operating System and Compiler, Addison-Wesley, 1992.
 T.D. Brown: C for FORTRAN Programmers, Silicon Press, 1990.
 R. Schäfer, F. Bomarius: Modula2C. Ein Übersetzer von
Modula-2 nach C, Report 178, Universität Kaiserslautern, 1988.
 C.A. Wiatrowski, R.S. Wiener: From C to Modula-2 and Back.
Bridging the Language Gap, Wiley & Sons, 1987.
 J.T. Smith: C++ for Scientists and Engineers, McGraw-Hill, 1991.
 Fortran and C in Scientific Computing, Brunel Conference Center, London, 1993.
 C. Überhuber, P. Meditz: Software-Entwicklung in Fortran 90, Springer, 1993.
 A.J.E. van Delft: Comments on Oberon, SIGPLAN Notices, Vol. 24 Iss. 3 p. 23-30, 1989.
 H. Mössenböck: Object-oriented Programming in Oberon-2, Springer, 1993.
 G. Blaschek, G. Pomberger, A. Stritzinger: A Comparison of
Object-Oriented Programming Languages, Structured Programming, Vol. 10 Iss. 4 p. 187-197, 1989.
 R. Henderson, B. Zorn: A Comparison of Object-oriented
Programming in Four Modern Languages, Software - Practice and Experience, Vol. 24 Iss. 11 p. 1077-1095, 1994.
 J. Templ: Vergleich der Programmiersprachen Oberon und C++,
iX. Multiuser. Multitasking, Iss. 9 p. 138-143, 1994.
 R. Griesemer: A Programming Language for Vector Computers, dissertation, ETH Zürich, 1993.
 P.D. Stotts: A Comparative Survey of Concurrent Programming
Languages, ACM SIGPLAN Notices, Vol. 17 Iss. 10 p. 50-61, 1982.
A Comparison of C++, FORTRAN 90 and Oberon-2 for Scientific Programming,
editors: Friedbert Huber-Wäschle, Helmut Schauer, Peter Widmayer
Berlin, Springer, p. 740-748, 1995.
Full german title:
GISI 95: Herausforderungen eines globalen Informationsverbundes für die Informatik.
25. GI-Jahrestagung und 13. Schweizer Informatikertag,
Zürich, 18-20. September 1995, ISBN 3-540-60213-5
© Copyright 1995-1998 ARITHMETICA,
webmaster page update 1998.05.19.