57.8.10 – #undef
The #undef directive cancels a previously defined macro
replacement. Any other macro replacements that occurred before the
#undef directive remain.
The #undef directive has the following syntax:
#undef identifier
57.9 – Predefined Macros
In addition to the ANSI-compliant, implementation-independent macros described in the HP C Language Reference Manual, The VSI C compiler provides the following predefined macros:
57.9.1 – System Identification Macros
Each implementation of the VSI C compiler automatically defines
macros that you can use to identify the system on which the program
is running. These macros can assist in writing code that executes
conditionally, depending on the architecture or operating system on
which the program is running.
The following table lists the traditional and new spellings of
these predefined macro names for VSI C on OpenVMS systems. Both
spellings are defined for each macro unless ANSI C mode is in
effect (/STANDARD=ANSI89), in which case only the new spellings are
defined.
Traditional spelling New spelling
vms __vms
VMS __VMS
vms_version __vms_VERSION
VMS_VERSION __VMS_VERSION
__VMS_VER
__DECC_VER
__DECCXX_VER
vaxc __vaxc
VAXC __VAXC
vax11c __vax11C
VAX11C __VAX11C
--- __DECC
--- __STDC__
__STDC_HOSTED__
__STDC_VERSION__
__STDC_ISO_10646__
__MIA
On OpenVMS I64 Systems, VSI C also supports the following
predefined system identification macro names in all compiler modes:
__ia64
__ia64__
__32BITS
__INITIAL_POINTER_SIZE
Predefined macros (with the exception of __STDC_VERSION__,
__STDC_ISO_10646__, vms_version, VMS_VERSION, __vms_version,
__VMS_VERSION, and __INITIAL_POINTER_SIZE) are defined as 1 or 0,
depending on the system you're compiling on (VAX or Alpha
processor), the compiler defaults, and the qualifiers used. For
example, if you compiled using G_floating format, then __D_FLOAT
and __IEEE_FLOAT (Alpha processors only) are predefined to be 0,
and __G_FLOAT is predefined as if the following were included
before every compilation unit:
#define __G_FLOAT 1
These macros can assist in writing code that executes
conditionally. They can be used in #elif, #if, #ifdef, and #ifndef
directives to separate portable and nonportable code in a VSI C
program. The vms_version, VMS_VERSION, __vms_version, and
__VMS_VERSION macros are defined with the value of the OpenVMS
version on which you are running (for example, Version 6.0).
The __STDC__ macro is defined to 1 for /STANDARD options ANSI89,
C99, LATEST and MIA. It is defined to 2 for /STANDARD=RELAXED and
to 0 for /STANDARD=MS. It is not defined for /STANDARD options
VAXC and COMMON.
The __STDC_HOSTED__ macro is defined to 1 for /STANDARD=c99 and
/STANDARD=LATEST. It is not defined for all other /STANDARD
keywords.
The __STDC_VERSION__ macro is defined to 199901L for /STANDARD
keywords C99, LATEST, RELAXED, MS, PORTABLE. It is defined to
199409L when the ISOC94 keyword is specified alone or with the
ANSI89, MIA, RELAXED, MS, PORTABLE, or COMMON modes. The macro is
undefined for the VAXC keyword or for keywords ANSI89, MIA, or
COMMON without ISOC94 specified.
The __STDC_ISO_10646__ macro evaluates to an integer constant of
the form yyyymmL (for example, 199712L), intended to indicate that
values of type wchar_t are the coded representations of the
characters defined by ISO/IEC 10646, along with all amendments and
technical corrigenda as of the specified year and month.
57.9.2 – Compiler Mode Macros
The following predefined macros are defined as 1 if the corresponding compiler mode is selected (Otherwise, they are undefined): __DECC_MODE_STRICT ! /STANDARD=ANSI89 __DECC_MODE_RELAXED ! /STANDARD=RELAXED __DECC_MODE_VAXC ! /STANDARD=VAXC __DECC_MODE_COMMON ! /STANDARD=COMMON __STDC__ ! /STANDARD=ANSI89, /STANDARD=RELAXED __STDC_VERSION__ ! /STANDARD=ISOC94 __MS ! /STANDARD=MS
57.9.3 – Floating Point Macros
VSI C automatically defines the following predefined macros pertaining to the format of floating-point variables. You can use them to identify the format with which you are compiling your program: __D_FLOAT __G_FLOAT __IEEE_FLOAT _IEEE_FP __X_FLOAT
57.9.4 – RTL Standards Macros
VSI C defines the following macros that you can explicitly define (using the /DEFINE qualifier or the #define preprocessor directive) to control which VSI C RTL functions are declared in header files and to obtain standards conformance checking: _XOPEN_SOURCE_EXTENDED _XOPEN_SOURCE _POSIX_C_SOURCE _ANSI_C_SOURCE _VMS_V6_SOURCE _DECC_V4_SOURCE __BSD44_CURSES __VMS_CURSES _SOCKADDR_LEN
57.9.5 – HIDE FORBIDDEN NAMES
The ANSI C standard specifies exactly what identifiers in the
normal name space are declared by the standard header files. A
compiler is not free to declare additional identifiers in a header
file unless the identifiers follow defined rules (the identifier
must begin with an underscore followed by an uppercase letter or
another underscore).
When you compile with VSI C using any values of /STANDARD that set
strict C standard conformance (ANSI89, MIA, C99, and LATEST),
versions of the standard header files are included that hide many
identifiers that do not follow the rules. The header file
<stdio.h>, for example, hides the definition of the macro TRUE.
The compiler accomplishes this by predefining the macro
__HIDE_FORBIDDEN_NAMES for the above-mentioned /STANDARD values.
You can use the command line qualifier
/UNDEFINE="__HIDE_FORBIDDEN_NAMES" to prevent the compiler from
predefining this macro, thus including macro definitions of the
forbidden names.
The header files are modified to only define additional VAX C names
if __HIDE_FORBIDDEN_NAMES is undefined. For example, <stdio.h>
might contain the following:
#ifndef __HIDE_FORBIDDEN_NAMES
#define TRUE 1
#endif
57.9.6 – CC$gfloat
When you compile using the /G_FLOAT qualifier, CC$gfloat is defined as 1. When you compile without the /G_FLOAT qualifier, CC$gfloat is defined as 0. The CC$gfloat macro is provided for compatiblity with VAX C. The __G_FLOAT predefined macro should be used instead.
57.9.7 – DATE
The __DATE__ macro evaluates to a string specifying the date on
which the compilation started. The string presents the date in the
form "Mmm dd yyyy" The names of the months are those generated by
the asctime library function. The first d is a space if dd is less
than 10.
Example:
printf("%s",__DATE__);
57.9.8 – FILE
The __FILE__ macro evaluates to a string literal specifying the
file specification of the current source file.
Example:
printf("file %s", __FILE__);
57.9.9 – LINE
The __LINE__ macro evaluates to a decimal constant specifying the
number of the line in the source file containing the macro
reference.
Example:
printf("At line %d in file %s", __LINE__, __FILE__);
57.9.10 – TIME
The __TIME__ macro evaluates to a string specifying the time that
the compilation started. The time has the following format:
hh:mm:ss
Example:
printf("%s", __TIME__);
The value of this macro remains constant throughout the translation
unit.
57.10 – Predeclared Identifiers
57.10.1 – __func__
The __func__ predeclared identifier evaluates to a static array of
char, initialized with the spelling of the function's name. It is
visible anywhere within the body of a function definition.
Example:
void foo(void) {printf("%s\n", __func__);}
This function prints "foo".
57.11 – Statements
Statements are the executable instructions performed by the program. Statements produce values and control program flow. A group of statements enclosed in braces makes up a block. Any valid expression or declaration terminated by a semicolon is considered a statement. The statements that control program flow are described in further HELP frames. See also HELP CC LANGUAGE_TOPICS DECLARATION and HELP CC LANGUAGE_TOPICS PREPROCESSOR.
57.11.1 – break
The break statement terminates the immediately enclosing while, do,
for, or switch statement. Control passes to the statement
following the terminated statement.
Syntax:
break ;
57.11.2 – continue
The continue statement passes control to the test portion of the
immediately enclosing while, do, or for statement.
Syntax:
continue ;
In each of the following statements, a continue statement is
equivalent to "goto label;":
while (expression) { statement ... label: ; }
do { statement ... label: ; } while (expression);
for (expression; expression; expression)
{ statement ... label: ; }
The continue statement is not intended for switches. A continue
statement inside a switch statement inside a loop causes
reiteration of the loop.
57.11.3 – do
The do statement executes a statement one or more times, as long as
a stated condition expression is true.
Syntax:
do statement while ( expression ) ;
The do statement is executed at least once. The expression is
evaluated after each execution of the statement. If the expression
is not 0, the statement is executed again. The statement following
the do statement (the body of the do statement) is not optional;
the null statement (a lone semicolon) is provided for specifying a
do statement with an empty body.
57.11.4 – for
The for statement executes a statement zero or more times, with
three specified control expressions. Expression-1 is evaluated
only once, before the first iteration; expression-2 is evaluated
before every iteration; expression-3 is evaluated after every
iteration. The for loop terminates if, on evaluation, expression-2
is 0.
Syntax:
for ( [expression-1] ; [expression-2] ; [expression-3] )
statement
The for statement is equivalent to the following format:
expression-1;
while ( expression-2 ) { statement expression-3; }
You can omit any of the three expressions. If expression-2 is
omitted, the while condition is true.
57.11.5 – goto
The goto statement transfers control unconditionally to a labeled
statement.
Syntax:
goto identifier ;
The identifier must be a label located in the current function.
You may use goto to branch into a block, but no initializations are
performed on variables declared in the block.
57.11.6 – if
The if statement is a conditional statement. It can be written
with or without an else clause as follows:
if ( expression ) statement
if ( expression ) statement else statement
In both cases, the expression is evaluated, and if it is not 0, the
first statement is executed. If the else clause is included and
the expression is 0, the statement following else is executed
instead. In a series of if-else clauses, the else matches the most
recent else-less if.
57.11.7 – Labeled
Any statement can be preceded by a label prefix of the following
form:
identifier:
This declares the identifier as a label. The scope of such a
declaration is the current function. Labels are used only as the
targets of goto statements.
57.11.8 – Null
A null statement is a semicolon:
;
The null statement provides a null action -- for example, the body
of a for loop that takes no action:
for(i=0; i < ARRAYSIZE && x[i] == 5; i++)
;
57.11.9 – return
The return statement causes a return from a function, with or
without a return value.
Syntax:
return ;
return expression ;
The return value is undefined if not specified in a return
statement. If an expression is specified in the return statement,
it is evaluated and the value is returned to the calling function;
the value is converted, if necessary, to the type with which the
called function was declared. If a function does not have a return
statement, the effect (on reaching the end of the function) is the
same as with a return statement that does not specify an
expression. Functions declared as void may not contain return
statements specifying an expression.
57.11.10 – switch
The switch statement executes one or more of a series of cases,
based on the value of an integer expression.
Syntax:
switch ( expression ) body
The switch's body typically is a block, within which any statement
can be prefixed with one or more case labels as follows:
case constant-expression :
At most one statement in the body may have the label as follows:
default :
The switch expression is evaluated and compared to the cases. If
there is a case matching the expression's value, it is executed; if
not, the default case is executed. The switch is normally
terminated by a break, return, or goto statement in one of the
cases. If there is no matching case and no default, the body of
the switch statement is skipped.
57.11.11 – while
The while statement executes a statement 0 or more times, as long
as a stated condition is true.
Syntax:
while ( expression ) statement
The expression is evaluated before each execution, and the
statement is executed if the expression is not 0. The statement
following the parentheses (the body of the while statement) is not
optional; the null statement (a lone semicolon) is provided for
specifying a while statement with an empty body.
57.12 – Storage Classes
The storage class of a variable determines when its storage is allocated, whether its contents are preserved across different blocks or functions, and what link-time scope the variable has. Auto variables are allocated at run time. They are not preserved across functions. Auto is the default storage class for variables declared within a function. Extern variables are allocated at compile time. They are preserved across functions. There can be only 65,532 extern variables per program. Extern is the default storage class for variables declared outside a function. Globaldef, globalref, and globalvalue variables are allocated at compile time. They are preserved across functions. The number of global symbols is unlimited. Register variables are allocated at run time. They cannot be referenced from other separately compiled functions. Static variables are allocated at compile time. If externally declared, they retain their values across functions. If internally declared (inside of a function), they cannot be referenced from other functions; if control passes from the defining function, to other functions, and then passed back to the defining function, the variable retains its previous value and is not reinitialized.
57.13 – Type Qualifiers
Data-type qualifiers affect the allocation or access of data storage. The data-type qualifiers are const, volatile, __restrict, and __unaligned.
57.13.1 – const
The const data-type qualifier restricts access to stored data. If
you declare an object to be of type const, you cannot modify that
object. You can use the const data-type qualifier with the
volatile data-type qualifier or with any of the storage-class
specifiers or modifiers. The following example declares the
variable x to be a constant integer:
int const x;
57.13.2 – volatile
The volatile data-type qualifier prevents an object from being stored in a machine register, forcing it to be allocated in memory. This data-type qualifier is useful for declaring data that is to be accessed asynchronously. A device driver application often uses volatile data storage. Like const, you can specify the volatile data-type qualifier with any of the storage-class specifiers or modifiers with the exception of the register storage class.
57.13.3 – __restrict
The __restrict data-type qualifier is used to designate a pointer as pointing to a distinct object, thus allowing compiler optimizations to be made.
57.13.4 – __unaligned
This data-type qualifier is used in pointer definitions, indicating to the compiler that the data pointed to is not properly aligned on a correct address. (To be properly aligned, the address of an object must be a multiple of the size of the type. For example, two-byte objects must be aligned on even addresses.) When data is accessed through a pointer declared __unaligned, the compiler generates the additional code necessary to copy or store the data without causing alignment errors. It is best to avoid use of misaligned data altogether, but in some cases the usage may be justified by the need to access packed structures, or by other considerations.
57.14 – Storage Class Modifiers
The storage-class modifiers allow individual attributes of a
variable to change without changing the other default attributes
connected with a given storage class. Storage-class keywords and
storage-class modifiers can be specified in either order.
Syntax:
modifier storage_class_keyword identifier;
If you specify a storage-class modifier but not a storage class
keyword, the storage class defaults to extern.
57.14.1 – noshare
Noshare variables are assigned the PSECT attribute NOSHR. Noshare
variables may not be shared between processes. This modifier is
used when linking variables that are not to be shared within a
shareable image. You can use the noshare modifier with the
storage-class keywords static, [extern], globaldef, and
globaldef{"name"}.
57.14.2 – readonly
Readonly variables are assigned the PSECT attribute NOWRT and are
stored in the PSECT $READONLY$ which is a nonwritable data area.
Other programs can access the PSECT directly, but none of the
information can be overwritten. You can use the readonly modifier
with the storage-class keywords [extern], static, globaldef, and
globaldef{"name"}.
You can use both the readonly and noshare modifiers with the
[extern] and the globaldef{"name"} specifiers. If you use both
modifiers with either the static or the globaldef specifiers, the
compiler ignores noshare and accepts readonly.
57.14.3 – _align
The _align modifier allows you to align objects of any of the VSI C
data types on a specified storage boundary. Use the _align
modifier in a data declaration or definition.
When specifying the boundary of the data alignment, you can use a
predefined constant: BYTE or byte, WORD or word, LONGWORD or
longword, QUADWORD or quadword, OCTAWORD or octaword, and PAGE or
page.
You can also specify an integer value that is a power of two. The
power of two tells VSI C the number of bytes to pad in order to
align the data:
For OpenVMS VAX systems, specify a constant 0, 1, 2, 3, 4, or 9.
For OpenVMS Alpha systems, specify any constant from 0 to 16.
57.14.4 – __align
The __align storage-class modifier has the same semantic meaning as the _align keyword. The difference is that __align is a keyword in all compiler modes while _align is a keyword only in modes that recognize VAX C keywords. For new programs, using __align is recommended.
57.14.5 – __forceinline
Similar to the __inline storage-class modifier, the __forceinline
storage-class modifier marks a function for inline expansion.
However, using __forceinline on a function definition and prototype
tells the compiler that it must substitute the code within the
function definition for every call to that function. (With
__inline, such substitution occurs at the discretion of the
compiler.)
Syntax:
__forceinline [type] function_definition
57.14.6 – __inline
The __inline 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 specifier has the same
effect as the #pragma inline preprocessor directive, except that
the latter attempts to provide inline expansion for all functions
in a translation unit, rather than for selected functions.
Syntax:
__inline [type] function_definition
57.14.7 – inline
Similar to the __inline storage-class modifier, the inline
storage-class modifier can be used as a declaration specifier in
the declaration of a function. This modifier is supported in
relaxed ANSI C mode (/STANDARD=RELAXED) or if the
/ACCEPT=C99_KEYWORDS or /ACCEPT=GCCINLINE qualifier is specified.
With static functions, inline has the same effect as applying
__inline or #pragma inline to the function.
However, when inline is applied to a function with external
linkage, besides allowing calls within that translation unit to be
inlined, the inline semantics provide additional rules that also
allow calls to the function to be inlined in other translation
units or for the function to be called as an external function, at
the compiler's discretion:
o If the inline keyword is used on a function declaration with
external linkage, then the function must also be defined in the
same translation unit.
o If all of the file scope declarations of the function use the
inline keyword but do not use the extern keyword, then the
definition in that translation unit is called an inline
definition, and no externally-callable definition is produced
by that compilation unit.
Otherwise, the compilation unit does produce an
externally-callable definition.
o An inline definition must not contain a definition of a
modifiable object with static storage duration, and it must not
refer to an identifier with internal linkage. These
restrictions do not apply to the externally-callable
definition.
o As usual, at most one compilation unit in an entire program can
supply an externally-callable definition of a given function.
o Any call to a function with external linkage may be translated
as a call to an external function, regardless of the presence
of the inline qualifier. It follows from this and the previous
point that any function with external linkage that is called
must have exactly one externally-callable definition among all
the compilation units of an entire program.
o The address of an inline function with external linkage is
always computed as the address of the unique
externally-callable definition, never the address of an inline
definition.
o A call to inline function made through a pointer to the
externally-callable definition may still be inlined or
translated as a call to an inline definition, if the compiler
can determine the name of the function whose address was stored
in the pointer.
58 – Link libraries
The following describes how to link with the VSI C Run-Time Library
(RTL).
On I64 systems, you link to the VSI C RTL by using the C RTL
shareable image IA64$LIBRARY:DECC$SHR.EXE, which the linker
automatically finds through IMAGELIB.OLB.
Because DECC$SHR.EXE has only prefixed names (no unprefixed names),
to successfully link against it, make sure you cause prefixing to
occur for all VSI C RTL entry points. Do this by compiling in one
of two ways:
1. Compile with the /PREFIX_LIBRARY_ENTRIES=ALL_ENTRIES qualifier.
2. Compile with the /STANDARD=VAXC or /STANDARD=COMMON qualifier.
You get /PREFIX_LIBRARY_ENTRIES=ALL_ENTRIES as the default.
After making sure that all VSI C RTL entry points are prefixed,
link against the shareable image using the LINK command. For
example:
$ CC/DECC/PREFIX_LIBRARY_ENTRIES=ALL_ENTRIES PROG1
$ LINK PROG1
The linker automatically searches IMAGELIB.OLB to find
DECC$SHR.EXE, and resolves all C RTL references.
59 – Run-time functions
For help on the C run-time library (C RTL) functions supplied with
your OpenVMS operating system, enter the following:
$ HELP CRTL
Also see the HP C Run-Time Library Reference Manual for OpenVMS
Systems.
60 – Release Notes
The release notes for VSI C are contained in the following files: SYS$HELP:CC.RELEASE_NOTES SYS$HELP:CC_RELEASE_NOTES.PS
61 – Socket Routines
For help on the socket routines used for writing Internet
application programs for the TCP/IP Services protocol, enter the
following:
$ HELP TCPIP_Services Programming_Interfaces Sockets_API
Also see the HP TCP/IP Services for OpenVMS product documentation.