HP OpenVMS Systems

C Programming Language
Content starts here

Compaq C V6.4 for OpenVMS VAX Release Notes

Previous Contents

7 Compaq C for OpenVMS VAX Release Notes

7.1 New Features in Compaq C V6.4

In addition to the support for installing multiple compiler versions, this version provides most of the language-feature support for the new C99 standard that will be implemented for VAX. The C99 standard (ISO/IEC 9899:1999) was published by ISO in December, 1999 and adopted as an ANSI standard in April, 2000. An official copy of the standard can be purchased and downloaded as a PDF file for less than $20US from either NCITS or ANSI.

While Compaq C for OpenVMS Alpha will support all of C99, the VAX version is intended to provide only those features whose implementation is shared with Alpha. In particular, features that involve changes to the VAX code generator or to VAX-specific run-time libraries are not planned. Most notably, the new data types "_Complex" and "long long int" are not planned for VAX, nor are the new C99 "type-generic" math library functions, other new math functions, or the hexadecimal notation for floating point values. [Note that since the new C99 "long long int" data type is not implemented for VAX, there is no change to the rules for determining the type of a decimal integer constant; only the Alpha implementation is affected by the new C99 rules for decimal integer constants.]

The following specific enhancements were made:

  • Language modes, /STANDARD=C99 , and message groups
    The compiler's default language mode remains /STANDARD=RELAXED_ANSI89, which accepts nearly all language extensions as well as standard C89 and C99 features. It excludes only K&R ("common" mode), VAX C, and Microsoft features that conflict with standard C. The /STANDARD=ANSI89 mode continues to implement strictly the 1990 ANSI/ISO C standard (commonly called C89), issuing all required diagnostics as well as a number of optional diagnostics that help detect source code constructs that are not portable under the C89 standard (digraphs from the 1994 Amendment are also recognized in this mode, even though they were not specified in the 1990 standard). The ISOC94 keyword can still be added to any of the modes (except VAXC) to predefine the macro __STDC_VERSION__, as specified in Amendment 1 to the C89 standard.

    The command line will recognize a new language mode qualifier, /STANDARD=C99, but it will issue a warning and treat it exactly the same as /STANDARD=RELAXED_ANSI89, which accepts all of the C99 features that are implemented for VAX.

    Since the standard is quite new, use of C99 features is not really portable in a practical sense yet. Also, the term "ANSI C" or "standard C" will be ambiguous for some time to come (i.e. do you mean C89 or C99). To help with this situation, the compiler has added three new message groups for messages that report the use of features in the following categories:

    noc89  - features not in C89
    noc99  - features not in C99
    newc99 - features that are new in C99.
    The existing group, noansi , which is now somewhat ambiguous in name, is retained as a synonym for noc89.

  • #pragma names
    This pragma offers the same kinds of control over the mapping of external identifiers into object module symbols as does the command line qualifier /NAMES, and it uses the same keywords (except that the "lowercase" keyword is not supported). But as a pragma, the controls can be applied selectively to regions of declarations. The pragma has a save/restore stack that is also managed by #pragma environment , and so it is well-suited to use in header files. The effect of " #pragma environment header_defaults " is to set NAMES to "uppercase,truncated", which is the compiler default.

    One important use for this feature is to make it easier to use command line option /NAMES=AS_IS . Both the C99 standard and the C++ standard require that external names be treated as case-sensitive, and 3rd party libraries and Java native methods are starting to rely on case-sensitivity (C99 requires a minimum of 31 characters significant, while C++ requires all characters significant). Therefore we expect the use of /NAMES=AS_IS to become much more widespread.

    The Compaq C run-time library was implemented with all symbols duplicated and spelled both in uppercase and lowercase to allow C programs compiled with any of the /NAMES= settings to work. But traditional practice on OpenVMS combined with compiler defaults of /NAMES=UPPER has resulted in nearly all existing object libraries and shared images to contain all uppercase names (both in references and in definitions), even though C source code using these libraries typically declares the names in lowercase or mixed case. Usually, the header files to access these libraries contain macro definitions to replace lowercase names by uppercase names to allow client programs to be compiled /NAMES=AS_IS. But macro definitions are problematic because every external name has to have a macro.

    The new pragma allows header files to specify just once that the external names they declare are to be uppercased in the object module, regardless of the NAMES setting used in the rest of the compilation. The NAMES setting in effect at the first declaration of an external name is the one that takes effect, thus the setting specified in a header file will not be overridden by a subsequent redeclaration in the user's program (which might specify a different NAMES setting). Note that the automatic Prologue/Epilogue header file inclusion feature described in section 1.7.4 of the User's Guide (in connection with pointer_size pragmas) can also be used to specify the NAMES setting for all headers in a given directory or text library, without having to edit each header directly.

    #pragma names <stack-option>
    #pragma names <case-option>[, <length-option>]
    #pragma names <length-option>[, <case-option>]
    Where <stack-option> is one of:
        save      - save the current names state
        restore   - restore a saved names state
    <case-option> is one of:
        uppercase - uppercase external names
        as_is     - do not change case
    and <length-option> is one of
        truncated - truncate at 31 characters
        shortened - shorten to 31 using CRC

  • New " _m " suffix forces pragmas to expand macros
    As specified in the Language Reference Manual, there is a fixed "grandfathered" list of #pragma directives that always undergo macro expansion in the preprocessor before being translated. No other #pragma directives normally undergo macro expansion. But since there are sometimes circumstances where macro expansion is needed on a particular instance of a pragma, a general mechanism has been added such that spelling the name of a #pragma directive with a trailing " _m " suffix will cause that directive to undergo macro expansion. An example of use follows in the next bullet item for #pragma assert non_zero . The suffix is permitted on all pragmas, including those that are already specified as undergoing macro expansion (in which case it has no effect).

  • New non_zero keyword for #pragma assert
    This new keyword allows you to assert that a particular constant-expression must be non-zero at compile time, and supply a text string to be output if the assertion proves false. The text string is output with a warning message that includes the source text of the expression.

       #pragma assert non_zero(<constant-expression>) <string-literal>
    Note that the constant-expression is a C language constant-expression, not just a preprocessor #if expression. And while #pragma assert itself does not perform macro expansion, the alternate form #pragma assert_m can be used to cause macro expansion to take place, which is most often what is desired, as in the second example below (since "offsetof" is a macro).

       #pragma assert   non_zero(sizeof(a) == 12) "wrong size a"
       #pragma assert_m non_zero(offsetof(s,b) == 4) "wrong offset b"
    If the sizeof a is not 12, and the offset of member b in the struct named by type b is not 4, the following diagnostics are output:

     CC-W-ASSERTFAIL, The assertion "(sizeof(a) == 12)" was not true.
     wrong size a.
     CC-W-ASSERTFAIL, The assertion "(offsetof(s,b) == 4)" was not true.
     wrong offset b.

  • New use of static keyword in array bounds.
    C99 permits the keyword " static " to be used within the outermost array bound of a formal parameter in a prototype function declaration. The effect is to assert to the compiler that at each call to the function, the corresponding actual argument will provide access to at least as many array elements as are specified in the declared array bound. Consider the following two function definitions:

    void foo(int a[1000]){ ... }
    void bar(int b[static 1000]) { ... }
    The declaration of foo is absolutely equivalent to one that declares "a" to be "int *". When compiling the body of foo, the compiler has no information about how many array elements may exist. The declaration of bar differs in that it asserts to the compiler that it may assume that at least 1000 array elements exist and may be safely accessed. The intent is to provide a hint to the optimizer about what can be safely pre-fetched.

  • New type _Bool
    This is the C99-specified boolean type. It is not recognized in VAXC, COMMON, or the strict ANSI89 mode. An object of this type occupies one byte and is an unsigned integer, but its value can only be either 0 or 1. It is permitted to use _Bool as the type for a bit-field. When a value of any scalar type (any arithmetic type including floating point and the new complex types, or any pointer type) is converted to _Bool, the result is zero if the value would compare equal to 0 (e.g. if the pointer is NULL), and otherwise the result is 1. It is intended to be used in conjuction with a new standard header, <stdbool.h>, but that is not required. The content of the new header is simply as follows:

    #define bool _Bool
    #define true 1
    #define false 0
    #define __bool_true_false_are_defined 1

  • New type keywords _Complex and _Imaginary
    Although neither of these C99 types will be implemented on VAX, their use will be diagnosed. Since these names begin with an underscore followed by an uppercase letter, they are in the namespace reserved to the C implementation and should not be used even in strict ANSI89 mode.

7.2 New Features in Compaq C V6.2

This release primarily contains a number of new language features from the in-process revision to the C standard, C9X (expected to be C99), and from the gcc compiler (to aid compatibility with source code from Linux systems). It also has diagnostic message improvements, as well as bug fixes and miscellaneous improvements.

The following specific enhancements were made:

  • more html-format documentation
    The Compaq C manuals, help, and release notes are now installed in html form in a subdirectory of SYS$HELP. They can be accessed from a locally-running browser through


    To access these documents from a browser running on a different system, you can copy the entire directory contents to a directory or server system that is accessible to your browser.
  • diagnostic for unbalanced pragma state save/restore
    The compiler now issues a diagnostic when a #pragma stack is not empty at the end of a compilation (i.e. when the program issues a #pragma <pragma-name> save directive without ever issuing a corresponding #pragma <pragma-name> restore
  • additional diagnostics to help locate unmatched braces
    When a closing brace is omitted, the parser error is generally reported against a location far from the point of the actual coding error. Additional diagnostics now attempt to find which opening brace was not matched, based on heuristic observation of the indentation style used in the rest of the source code. In testing, these messages have proved quite accurate, but if the source code is very inconsistent in this style, or uses an unusual style, the messages may not be very effective. We would appreciate feedback on this feature, particularly testcases where the diagnostic misidentified which brace was unmatched.
  • new keywords for /accept qualifier
    New keywords for the /accept command line qualifier:
    • [no]c99_keywords
      Controls whether or not the new keywords being introduced in the C standard that are in the C89 namespace for user identifiers (inline and restrict) are accepted without double leading underscores.
    • [no]gccinline
      The gcc compiler implements an inline function qualifier for functions with external linkage that gives similar capabilites to the C9X feature described below, but the details of usage are somewhat different (basically the combination of extern and inline keywords makes an inline definition, instead of the exlusive use of the inline keyword without the extern keyword). This option controls which variation of the feature is implemented.
  • extern inline functions (C9X and gcc)
    A new keyword, inline , has been introduced which can be used as a declaration specifier in the declaration of a function. With static functions, this has the same effect as applying #pragma inline to the function. When the specifier is applied to a function with external linkage, besides suggesting to the compiler that calls within that translation unit be inlined, there are additional rules that allow calls to the function also to be inlined in other translation units or else called as an external function at the compiler's discretion:
    • 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.
    • 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.
    • 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.
    • As usual, at most one compilation unit in an entire program can supply an externally-callable definition of a given function.
    • 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.
    • 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.
    • A call to an 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.
  • intermixed declarations and code, "for" loop declarations (C9X and gcc)
    The C++ language has always allowed these, and they are now being added to C. The rules are the same as for C++. Within a compound statement, statements and declarations may be freely interspersed. This allows declarations to be placed nearer to their point of first use without introducing additional nested compound statements.
    And in the for statement, the first clause may be a declaration whose scope includes the remaining clauses of the for header and the entire loop body. This is normally used to declare and initialize a local loop control variable, e.g.

        for (int i=0; i<10; i++)
            printf("%d\n", i);
  • __func__ predeclared identifier (C9X and gcc)
    Anywhere within the body of a function definition, code can assume that there is visible an identifier named __func__ that is declared as a static array of char initialized with the spelling of the function's name. E.g a function defined as

    void foo(void) {printf("%s\n", __func__);}

    will print "foo".
  • compound literals (C9X and gcc)
    A compound literal is a new form of expression that constructs the value of an object, including objects of array, struct, or union type. In C89, passing a struct value to a function typically involves declaring a named object of the type, initializing its members, and passing that object to the function. A compound literal is an unnamed object specified by syntax consisting of a parenthesized type name (i.e. the same syntax as a cast operator) followed by a brace-enclosed list of initializers. Note that the initializer list can use the recently-introduced designator syntax.
    E.g. to construct an array of 1000 ints that are all zero except for array element 5, which is to have a value of 7, you can write: (int [1000]){[5] = 7}.
    A compound literal object is an lvalue. The object it designates has static storage duration if it occurs outside of all function definitions, and otherwise has automatic storage duration associated with the nearest enclosing block.
  • comment introducers optionally detected within comments, to help find unterminated comments
    The new message "nestedcomment" can be enabled to report occurrences of "/*" inside of a comment introduced by "/*". This often indicates that a terminating "*/" was omitted, although certain coding practices may also produce many occurrences that are harmless. The message is also enabled by enabling the "level4", "unused", or "questcode" groups.
  • __align synonym for _align (ANSI namespace)
    The long-supported _align storage class modifier is in the namespace reserved for users' identifiers in some contexts under the C standard, and so it could not be recognized as a keyword in strict ANSI mode (/standard=ansi89). An alternate spelling with two leading underscores (putting it in the namespace reserved to the C implementation) is now recognized in all modes so that the feature can be used when compiling in strict ANSI mode.
  • __typeof__ unary operator (gcc)
    The gcc compiler provides an operator named "__typeof__" that can be used much like the standard C operator "sizeof", except that instead of producing a value (the size of an expression or type) it produces a type (the type of the expression or type that is its single operand). It can be convenient to use in macros for generating declarations or casts that use the same type as some expression or typename supplied as an argument to the macro.
  • pointer arithmetic on void and function pointers (gcc)
    Pointer arithmetic on void* pointers or pointers to functions formerly produced hard errors. The gcc compiler allows this, treating both as if they were char* pointers. This behavior has been adopted, with an appropriate warning instead of an error.
  • string initializers optionally enclosed in parentheses (gcc)
    In standard C, a string literal ordinarily has type char *. A special case is made when a string literal is the initializer for an array of char, in which case it is essentially treated as an array object that provides the values (and, in the case of an incomplete array, the size) of the array of char being initialized.
    Also in standard C, a string literal enclosed in parentheses is not itself a string literal, and so this special case would not apply - instead the parenthesized literal would be treated as a single pointer of type char *, which is not a valid initializer for an object of type array of char.
    The gcc compiler allows a parenthesized string literal to initialize a char array, and the construct commonly appears in Linux source code. So that behavior has been adopted, with an appropriate warning.
  • difference of addresses in same object are constants (gcc)
    If the & operator is used to obtain the addresses of two lvalues within the same object, and the lvalues are specified with integral constant expressions, then the result depends only on the layout of the object, and for practical purposes can be computed at compile time much like the integral constant expressions that are required to be produced by sizeof and offsetof.
    E.g. for any array "a" of int, the value of &a[4] - &a[3] must be sizeof(int), and sizeof(int) is an integral constant expression. But the C standard's specification of expressions that must be treated by the compiler as integral constant expressions does not include use of the & operator, and so &a[4] - &a[3] is not required to be treated as such, and Compaq C has not previously done so. But the C standard also explicitly recognizes that implementations may treat additional forms of expressions as constant expressions, and gcc and other compilers do treat these cases as integral constant expressions. Now Compaq C does as well.

7.3 New Features in DEC C V6.0

  • New command line qualifier /[NO]PROTOTYPES:

        default is /[NO]PROTOTYPES
    Syntax Description:
                Creates an output file containing function
                prototypes for all global functions defined in
                the module which is being compiled.
                negatable optional parameter, which indicates
                that identififer names are to be included in
                the prototype declarations that appear in the
                output file.  The default is NOIDENTIFIERS
                negatable optional parameter, which indicates
                that prototypes for static function
                definitions are to be included in the output
                file.  The default is NOSTATIC_FUNCTIONS
                an optional parameter specifying the output
                file name.  When not specified the output file
                name will be have the same defaults as listing
                file, except that the .CH file extension is
                used instead of the .LIS extension.
  • New command line qualifier, /SHOW=MESSAGES . This qualifier adds a new section to the listing file showing all of the compiler's diagnostic messages that are enabled at the start of the compilation, after the command line has been processed. The listing shows the message identifer, the severity, and the parameterized text of each enabled message, reflecting the effects of the /standard and /warnings command line qualifiers (except that severity-based suppression, /warnings=noinformationals or /nowarnings, is not reflected). The /warnings=verbose qualifier causes this listing to be expanded with the "Description" and "User Action" text following the text for each enabled message.
  • New informationals to report apparently unnecessary #include files and CDD records. The most useful of these, UNUSEDTOP, reports only headers explicitly #included at the top level in the compilation unit that did not provide anything used by the rest of the compilation. This message is enabled at level4. Other diagnostics to report on the effects of #includes nested within other headers, and on CDD records, are enabled at level5. All of these messages can be enabled by the message group UNUSED. Unlike any other messages, these messages must be enabled on the command line in order to be effective. The processing that analyzes the dependencies on included files is signficant, and it must be started before processing of the input files begins. Any #pragma message directives within the source have no effect on these messages, their state is determined only by processing the command line.
  • The builtin function __ALLOCA(), which has been available on Alpha since the earliest releases, has been implemented for VAX. Either #include <builtins.h> or use #pragma builtins to enable it.
  • Variable length arrays from the C9X review draft have been implemented. This feature permits array objects with auto storage class, and array typedefs declared at block scope, to have bounds that are runtime-computed expressions. It also permits the declaration and definition of functions whose parameters are arrays dimensioned by other parameters (similar to Fortran assumed-shape arrays). The following example illustrates both uses. Note that the definition of function sub() uses prototype syntax and that the dimension parameters precede the array parameter that uses them. In order to define a function with the dimension parameters following the array parameter that uses them, it is necessary to write the function definition using K&R syntax (since that syntax allows the declarations of the types of the parameters to be written in a different order from the parameters themselves). K&R function definitions should generally be avoided.

      #include <stdio.h>
      #include <stdlib.h>
      void sub(int, int, int[*][*]);
      int main(int argc, char **argv)
          if (argc != 3) {
              printf("Specify two array bound arguments.\n");
              int dim1 = atoi(argv[1]);
              int dim2 = atoi(argv[2]);
              int a[dim1][dim2];
              int i, j, k = 0;
              for (i = 0; i < dim1; i++) {
                  for (j = 0; j < dim2; j++) {
                      a[i][j] = k++;
              printf("dim1 = %d, dim2 = %d.",
              sub(dim1, dim2, a);
              sub(dim2, dim1, a);
      void sub(int sub1, int sub2, int suba[sub1][sub2])
          int i, j, k = 0;
          printf("\nIn sub, sub1 = %d, sub2 = %d.",
                            sub1,      sub2);
          for (i = 0; i < sub1; i++) {
              for (j = 0; j < sub2; j++) {
                  printf("%4d", suba[i][j]);

    Finally, note that variable length arrays can often be used in place of the non-standard __ALLOCA() builtin function, an important difference being that the storage allocated by __ALLOCA is not normally freed until return from the function containing the call, while the storage allocated for a variable length array is freed on exit from the block in which it is allocated. If __ALLOCA is called within the scope of a declaration for a variable length array object, an error is issued (MIXALLOCAVLAV). On the Alpha platform, such usage produces a warning and causes the storage allocated by __ALLOCA to be freed when the block containing the variable length array declaration is exited.

Previous Next Contents