With many of the processors supported by the HI-TECH C compilers there are more than one address space accessible to a program. Typically one address space is more economical to access than another, larger address space. Thus it is desirable to be able to tailor a prorgram's use of memory to achieve the greatest economy in addressing (thus minimizing program size and maximizing speed) while allowing access to as much memory as the program requires.
This concept of different address spaces is not catered for by either K&R or ANSI C (except to recognize the possibility of separate address spaces for code and data). Without any extensions to the language itself it is possible to devise more than one memory model for a given processor, selected at compile time. This has the effect of selecting one addressing method for all data and/or code. This permits the model for a particular program to be chosen depending on that program's memory requirements.
In many programs, however, only one or two data structures are large enough to need to be placed in the larger address space. Selection of a "large" memory model for the whole of the program makes the whole program larger and slower just to allow a few large data structures. This can be overcome by allowing individual selection of the address space for each data structure. Unfortunately this entails extensions to the language, never a desirable approach. To minimize the effect of such extensions they should satisfy the following criteria:
- As far as possible the extensions should be consistent with common practice.
- The extensions should fit a machine-independent model to maximize portability across processors and operating systems.
These goals have been achieved within HI-TECH C by means of the following model:
Each memory model defines three address spaces each for code and data. These address spaces are known as the near, far and default spaces. Any object qualified by the near keyword will be placed in the near address space, any object qualified by the far keyword shall be placed in the far address space, and all other objects shall be placed in the default address space. The near address space shall be a (possibly improper) subspace of the default address space, while the default address space shall be a (possibly improper) subspace of the far address space. There shall be up to three kinds of pointers corresponding to the three address spaces, each capable of addressing an object in its own address space or a subspace of that address space.
This implies that the address of an object may be converted to a pointer into a larger address space, e.g. a near object may have its address converted to a pointer to far, but a far object may not be able to be addressed by a pointer to near.
In practice the default address space will usually correspond exactly to either the near or far address spaces. If all three address spaces correspond to the same memory then there is only one memory model possible. This occurs with the 68000 processor. Where the default code and data spaces may each correspond to either the near or far address spaces then there will be a total of four memory models. This is the case with the 8086 processor.
The keywords far and near are supported by all the HI- TECH C compilers, but the exact correspondence of address spaces is determined by the individual characteristics of each processor and the choice of memory model (if there is a choice). However code written using these keywords will be portable providing it obeys the constraints of the model described above.
This model also corresponds well with other implementations using the near and far keywords, although such implementations do not appear to have been designed around a formal, portable model.