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
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:
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.
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
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
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
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
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.
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__);
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__);
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__);
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.
10 – Predeclared Identifiers
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".
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.
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 ;
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.
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.
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.
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.
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.
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.
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++) ;
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.
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.
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.
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.
13 – Type Qualifiers
Data-type qualifiers affect the allocation or access of data storage. The data-type qualifiers are const, volatile, __restrict, and __unaligned.
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;
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.
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.
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.
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.
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"}.
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.
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.
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.
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
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
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.