Many languages and tools have been designed for programming traditional serial scalar processors, but C and Fortran have undoubtedly proved to be the most popular among professionals. What is so special in these two languages that makes them so successful and generally recognized? The answer is that both C and Fortran support and facilitate development of software whose properties are considered basic and necessary by most professionals.
While Fortran is mostly used for scientific programming, the C language is more general purpose widely used for system programming. The C language can be adapted for programming in the Fortran-like style. Moreover any Fortran 77 program can be easily converted into an equivalent C program (in particular, the GNU Fortran 77 compiler is implemented as such a convertor). So it is reasonable to assume that apart from the traditional affection of scientific programmers for Fortran, the same properties make Fortran attractive for scientific programming and C for general purpose and especially for system programming. Therefore we will refer mostly to C while analyzing basic software properties that are to be supported by successful programming tools.
First of all, the C language allows one to develop highly efficient software for any particular serial scalar processor. This is because the language reflects all of the main features of the architecture having an effect on the program efficiency such as machine-oriented data types (short, char, unsigned, etc.), indirect addressing and address arithmetics (arrays, pointers and their correlation), and other machine-level notions (increment/decrement operators, the sizeof operator, cast operators, bit-fields, bitwise operators, compound assignments, etc.). The traditional serial scalar architecture is reflected in the C language with a completeness that allows programmers to write, for each serial scalar processor, programs having practically the efficiency of assembly code. In other words, the C language supports efficient programming.
Second, the C language is standardized as ANSI C, and all good C compilers support the standard. This allows programmers to write in C applications that, once developed and tested on one particular platform, will run properly on all platforms. In other words, the C language supports portable programming. Portability of C applications is determined not only by the portability of their source code but by the portability of used libraries as well. The C language provides especially high level of portability for computers running either the same operating system or operating systems of the same family (e.g., different clones of Unix). The point is that in addition to standard ANSI C libraries, a lot of other libraries are de facto standard in the framework of the corresponding family of operating systems. As for Unix systems, the high-quality portable GNU C compiler is often used on many platforms instead of native C compilers, which provides still more portability for source C code.
Third, the C language allows programmer to develop program units that can be separately compiled and correctly used by other programmers, while developing their applications, without knowledge of their source code. In other words, the C language supports modular programming. Obviously packages and libraries can only be developed with tools supporting modular programming.
Fourth, the C language provides a clear and easy-in-use programming model that ensures reliable programming. In addition to modularity it facilitates the development of really complex and useful applications. It is very difficult to find a balance between efficiency and lucidity as well as to combine lucidity and expressiveness. The C language is an exceptionally rare example of such harmony.
Finally, the C language supports not only efficient and portable but efficiently portable programming the serial scalar processors. It has been stressed that the C language reflects all the main features of this architecture that affect program efficiency. On the other hand, the C language hides such peculiarities of each particular processor that have no analogs in other processors of the architecture (the peculiarities of register storage, details of stack implementation, details of instruction sets, etc.). It allows writing portable applications that run efficiently on any particular serial scalar platform having both a high-quality C compiler and efficiently implemented libraries.
Note that any tool supporting efficiently portable programming also supports both efficient and portable programming. However, not every tool enabling both efficient and portable programming of its target architecture, has to enable efficiently portable programming of this architecture as well. Indeed, if some tool allows one to write a portable application as well as manually to optimize the application for every particular representative of the architecture, it does not mean that the application will run efficiently on every system of the architecture without changes in its source code.
Of course, the five properties above do not exhaust all possible properties that can appear important for one or another kind of software (fault tolerance for controlling software, scalability for parallel software, etc.). But these five are primary, and can be summarized in plain language as follows. Not too many programmers will want to use programming tools that subject them to these disadvantages.
Do not allow them to utilize efficiently the performance potential of their computers.
Do not allow them to write programs that can run on different computers.
Do not allow them to write program modules that can be used by other programmers.
Are based on a sophisticated set of ideas that make applications complex and tedious and also error-prone.
Do not allow them to write portable applications running efficiently over a target group of computers.
In this book parallel programming tools are mainly assessed from the point of view of how well they support these basic program properties.