To implement the solution to printing 1000 numbers in reverse order, we could define 1000 variables, and use 1000 read and print statements:

double num1, num2, ... num1000 scanf("%lf", &num1); scanf("%lf", &num2); ... scanf("%lf", &num1000); printf("%f\n", num1000); ... printf("%f\n", num2); printf("%f\n", num1);

double precision :: num1, num2, ... num1000 read *, num1 read *, num2 ... read *, num1000 print *, num1000 ... print *, num2 print *, num1

We now have a program of 2000 lines + the overhead code framing out the program, defining the variables, etc. This is clearly more effort than we want to put into a program, and the program is not at all flexible. Where would we be if we needed to do the same for a billion numbers?

An array is a variable that holds multiple values of the same
type. Each value in the array is distinguished from the others
using an integer *index*, also known as a
*subscript*. The term subscript comes from
mathematics, where we might specify one
*element* from of an array of values
such as K_{0}, K_{1},
... K_{n}.

In C, we make a variable into an array by providing the number of elements it contains in square brackets following the name. We then select an element by specifying the subscript in square brackets after the name. C subscripts always begin at 0 and end at the array size minus one.

#define LIST_SIZE 1000 double list[LIST_SIZE]; scanf("%lf", &list[0]); scanf("%lf", &list[1]); ... scanf("%lf", &list[999]); printf("%f\n", list[999]); ... printf("%f\n", list[1]); printf("%f\n", list[0]);

In Fortran, we make a variable into an array by providing the number of elements it contains in parentheses following the name. We then select an element by specifying the subscript in parentheses after the name. By default, Fortran subscripts begin at 1, but we can control this.

module constants integer, parameter :: LIST_SIZE=1000 end module double precision :: list(LIST_SIZE) read *, list(1) read *, list(2) ... read *, list(1000) print *, list(1000) ... print *, list(2) print *, list(1)

An array makes it much easier to allocate the space for 1000 double precision values, but we still have 2000 statements to read the list and print it backwards. Can we do better?

The only restriction on subscripts is that the must be integers. They may be constants, variables, or complicated expressions. As long as the value of the subscript is within the range of subscripts for the array, there is no problem.

Most commonly, subscripts are a simple variable which is controlled by a loop that traverses all valid subscripts for the array:

Variables used to subscript an array must have enough range.
A Fortran integer(1) or C char variable have a maximum value
of +127, so they cannot be used as subscripts for an array
of 1000 elements. A Fortran integer (integer(4)) variable
has a maximum value of 2^{31}-1
(a little over 2 billion), which is enough for
most arrays. It is possible on modern computers to have arrays
with more than 2 billion elements, so we may sometimes need to
use integer(8).

The C header files define an unsigned integer type called
`size_t`

which has the same number of bits as a
memory address on the underlying hardware. Hence, it is
guaranteed to be able to handle an array of any size. This
data type should be used for virtually all array subscripts in C.

#define LIST_SIZE 1000 double list[LIST_SIZE]; size_t c; for (c = 0; c < LIST_SIZE; ++c) scanf("%lf", &list[c]); for (c = LIST_SIZE-1; c >= 0; --c) printf("%f", list[c]);

module constants integer, parameter :: LIST_SIZE=1000 end module double precision :: list(LIST_SIZE) integer :: index do index = 1, LIST_SIZE read *, list(index) enddo do index = LIST_SIZE, 1, -1 print *, list(index) enddo

In Fortran, if we want to define multiple arrays of the same size, we
can use the *dimension* modifier instead
of specifying the dimension for every array variable.

double precision, dimension(LIST_SIZE) :: list1, list2, list3

Fortran also allows the programmer to choose any starting and ending subscripts desired. The default starting subscript is 1, so the following is equivalent to the examples above:

double precision :: list(1:LIST_SIZE)

For some arrays, it may not make sense to use a starting subscript of one. For example, if an array contains the probability of a driver in the U.S. having an accident based on their age, then subscripts less than 15 would be useless, since people under are not allowed to drive.

We should also specify the array dimensions using named constants to make the program more readable and easier to modify.

module constants integer, parameter :: MIN_AGE=15, MAX_AGE=120 end module program insurance double precision :: accident_probability(MIN_AGE : MAX_AGE) integer :: age ... do age = MIN_AGE, MAX_AGE print *, accident_probability(age) enddo ... end program

#include <stdio.h> #include <sysexits.h> #define MIN_AGE 15 #define MAX_AGE 120 int main() { double accident_probability[MAX_AGE - MIN_AGE + 1]; size_t age; for (age = MIN_AGE; age <= MAX_AGE; ++age) printf("%f\n", accident_probability[age - MIN_AGE]); return EX_OK; }