The VAX C compatibility mode of DEC C for OpenVMS Systems provides the noshare, readonly, and _align storage-class modifiers. These storage-class modifiers are also supported in the relaxed ANSI mode of the compiler, but their use elicits a warning message.
You can use a storage-class specifier and a storage-class modifier in any order; usually, the modifier is placed after the specifier in the source code. For example:
extern noshare int x; /* Or, equivalently . . . */ int noshare extern x;
The following sections describe each of the DEC C storage-class modifiers specific to OpenVMS systems.
The noshare storage-class modifier assigns the attribute NOSHR to the program section of the variable. Use this modifier to allow other programs, used as shareable images, to have a copy of the variable's psect without the shareable images changing the variable's value in the original psect.
When a variable is declared with the noshare modifier and a shared image that has been linked to your program refers to that variable, a copy is made of the variable's original psect to a new psect in the other image. The other program may alter the value of that variable within the local psect without changing the value still stored in the psect of the original program.
For example, if you need to establish a set of data that will be used by several programs to initialize local data sets, then declare the external variables using the noshare specifier in a DEC C program. Each program receives a copy of the original data set to manipulate, but the original data set remains for the next program to use. If you define the data as extern without the noshare modifier, a copy of the psect of that variable is not made; each program would be allowed access to the original data set, and the initial values would be lost as each program stores the values for the data in the psect. If the data is declared as const or readonly, each program is able to access the original data set, but none of the programs can then change the values.
You can use the noshare modifier with the static, extern, globaldef, and globaldef{"name"} storage-class specifiers. For more information about the possible combinations of specifiers and modifiers, and the effects of the storage-class modifiers on program-section attributes, see Section 4.8.
You can use noshare alone, which implies an external definition of storage class extern. Also, when declaring variables using the extern and globaldef{"name"} storage-class specifiers, you can use noshare, const, and readonly, together, in the declaration. If you declare variables using the static or the globaldef specifiers, and you use both of the modifiers in the declaration, the compiler ignores noshare and accepts const or readonly.
The readonly storage-class modifier, like the const data-type qualifier, assigns the NOWRT attribute to the variable's program section; if used with the static or globaldef specifier, the variable is stored in the $CODE psect, which has the NOWRT attribute by default.
You can use both the readonly and const modifiers with the static, extern, globaldef, and globaldef {"psect"} storage-class specifiers.
In addition, both the readonly modifier and the const modifier can be used alone. When you specify these modifiers alone, an external definition of storage class extern is implied.
The const modifier restricts access to data in the same manner as the readonly modifier. However, in the declaration of a pointer, the readonly modifier cannot appear between the asterisk and the pointer variable to which it applies.
The following example shows the similarity between the const and readonly modifiers. In both instances, the point variable represents a constant pointer to a nonconstant integer.
readonly int * point; int * const point;
The _align storage-class modifier aligns objects of any of the DEC C data types on a specified storage boundary. Use the _align modifier in a data declaration or definition.
For example, to align an integer on the next quadword boundary, you can use any of the following declarations:
int _align( QUADWORD ) data; int _align( quadword ) data; int _align( 3 ) data;
When specifying the boundary of the data alignment, you can either use a predefined constant or specify an integer value that is a power of 2. These constants, or explicit powers of 2, tell DEC C the number of bytes to pad in order to align the data. In the previous example, int _align ( 3 ) specifies an alignment of 23 bytes, which is 8 bytes-a quadword of memory.
Table 4-2 presents all the predefined alignment constants, their equivalent power of 2, and their equivalent number of bytes.
Constant | Power of 2 | Number of Bytes |
---|---|---|
BYTE or byte | 0 | 1 |
WORD or word | 1 | 2 |
LONGWORD or longword | 2 | 4 |
QUADWORD or quadword | 3 | 8 |
OCTAWORD or octaword | 4 | 16 |
PAGE or page | 16 (Alpha only) 9 (VAX only) |
65,536 (Alpha only) 512 (VAX only) |
The __inline storage-class modifier marks a function for inline expansion. Using __inline on a function definition and prototype tells the compiler that it can substitute the code within the function definition for every call to that function. Substitution occurs at the discretion of the compiler. The __inline storage-class modifier has the same effect as the #pragma inline preprocessor directive, except that #pragma inline attempts to provide inline expansion for all functions in a translation unit, rather than for selected functions (See Section 5.4.6).
Use the following form to designate a function for inline expansion:
__inline [type] function_definition
The compiler issues a warning if __inline is used in /STANDARD=PORTABLE mode, because this is an implementation-specific extension.
Here is an example of using __inline:
/* prototype */ __inline int x (float y); /* definition */ __inline int x (float y) { return (1.0); }