United States

Compaq C

# Compaq C
User's Guide for OpenVMS Systems

Previous | Contents | Index

## 1.4.7 Linker Error Messages

If the linker detects any errors while linking object modules, it displays messages indicating the cause and severity of the error. If any error or fatal error conditions occur (that is, errors with severities of E or F), the linker does not produce an image file.

The messages produced by the linker are descriptive, and you do not usually need additional information to determine the specific error. Some common errors that occur during linking are as follows:

- An object module has compilation errors.
  This occurs when you try to link a module that produced warning messages during compilation. You can usually link compiled modules for which the compiler generated messages, but verify that the modules will produce the output you expect.
- The input file has a file type other than OBJ and no file type was specified on the command line.
  If you do not specify a file type, the linker searches for a file that has a file type of OBJ by default. If the file is not an object file and you do not identify it with the appropriate file type, the linker signals an error message and does not produce an image file.
- You tried to link a nonexistent module.
  The linker signals an error message if you misspell a module name on the command line or if the compilation contains fatal diagnostics.
- A reference to a symbol name remains unresolved.
  An error occurs when you omit required module or library names from the command line and the linker cannot locate the definition for a specified global symbol reference. Consider, for example, the following LINK command for a main program module, OCEAN.OBJ, that calls the subprogram modules REEF.OBJ, SHELLS.OBJ, and SEAWEED.OBJ:

      $ LINK OCEAN, REEF, SHELLS

  Because SEAWEED is not linked, the linker issues the following error messages:

      %LINK-W-NUDFSYMS, 1 undefined symbol
      %LINK-I-UDFSYMS,        SEAWEED
      %LINK-W-USEUNDEF, module "OCEAN" references undefined symbol "SEAWEED"
      %LINK-W-DIAGISUED, completed but with diagnostics

If an error occurs when you link modules, you can often correct it by reentering the command and specifying the correct modules or libraries. If an error indicates that a program module cannot be located, you may be linking the program with the wrong RTL.

For a complete list of linker messages, see the OpenVMS System Messages and Recovery Procedures Reference Manual.

# 1.5 Running a Compaq C Program

After you link your program, you can use the DCL command RUN to execute it. The RUN command has the following format:

`RUN [/[NO]DEBUG] file-spec [/[NO]DEBUG]`

> ### /[NO]DEBUG

> An optional qualifier. Specify the /DEBUG qualifier to invoke the debugger if the image was not linked with it. You cannot use /DEBUG on images linked with the /NOTRACEBACK qualifier. If the image was linked with the /DEBUG qualifier and you do not want the debugger to prompt you, use the /NODEBUG qualifier. The default action depends on whether the file was linked with the /DEBUG qualifier.

> ### file-spec

> The file you want to run.

The execution of a program begins at the function whose identifier is `main` , or, if there is no function with this identifier, at the first function seen by the VMS linker.

Note Unexpected results might occur if you don't have a function called `main` .

The following example executes the image SAMPLE.EXE without invoking the debugger:

    $ RUN SAMPLE/NODEBUG

For more information on debugging programs, see Section C.1.

During execution, an image can generate a fatal error called an exception condition. When an exception condition occurs, the system displays an error message. Run-time errors can also be issued by the operating system or by utilities.

When an error occurs during the execution of a program, the program is terminated and the OpenVMS condition handler displays one or more messages on the currently defined SYS$ERROR device.

A message is followed by a traceback. For each module in the image that has traceback information, the condition handler lists the modules that were active when the error occurred, which shows the sequence in which the modules were called.

For example, if an integer divide-by-zero condition occurs, a run-time message like the following appears:

    %SYSTEM-F-INTDIV, arithmetic trap, integer divide by zero
        at PC=00000FC3, PSL=03C00002

This message is followed by a traceback message similar to the following:

    %TRACE-F-TRACEBACK, symbolic stack dump follows

    module name   routine name   line       rel  PC        abs PC
    A             C                 8      00000007      00000FC3
    B             main           1408      000002F7      00000B17

The information in the traceback message follows:

> ### module name

> The name or names of an image module that was active when the error occurred.

> The first module name is that of the module in which the error occurred. Each subsequent line gives the name of the caller of the module named on the previous line. In this example, the modules are A and B; main called C.

> ### routine name

> The name of the function in the calling sequence.

> ### line

> The compiler-generated line number of the statement in the source program where the error occurred, or at which the call or reference to the next procedure was made. Line numbers in these messages match those in the listing file (not the source file).

> ### rel PC

> The value of the PC (program counter). This value represents the location in the program image at which the error occurred or at which a procedure was called. The location is relative to the virtual memory address that the linker assigned to the code program section of the module indicated by module name.

> ### abs PC

> The value of the PC in absolute terms; that is, the actual address in virtual memory representing the location at which the error occurred.

Traceback information is available at run time only for modules compiled and linked with the traceback option in effect. The traceback option is in effect by default for both the CC and LINK commands. You may use the CC command qualifier /NODEBUG and the LINK command qualifier /NOTRACEBACK to exclude traceback information. However, traceback information should be excluded only from thoroughly debugged program modules.

# 1.6 Passing Arguments to the main Function

The `main` function in a Compaq C program can accept arguments from the command line from which it was invoked. The syntax for a `main` function is:

`int main(int argc, char *argv[ ], char *envp[ ]) {...}`

> ### argc

> The number of arguments in the command line that invoked the program.

> ### argv

> A pointer to an array of character strings that contain the arguments.

> ### envp

> The environment array. It contains process information such as the user name and controlling terminal. It has no bearing on passing command-line arguments. Its primary use in Compaq C programs is during `exec` and `getenv` function calls. (For more information, see the Compaq C Run-Time Library Reference Manual for OpenVMS Systems).

In the `main` function definition, the parameters are optional. However, you can access only the parameters that you define. You can define the `main` function in any of the following ways:

    int main()
    int main(int argc)
    int main(int argc, char *argv[ ])
    int main(int argc, char *argv[ ], char *envp[ ])

To pass arguments to the `main` function, you must install the program as a DCL foreign command. When a program is installed and run as a foreign command, the argc parameter is always greater than or equal to 1, and argv[0]always contains the name of the image file.

The procedure for installing a foreign command involves using a DCL assignment statement to assign the name of the image file to a symbol that is later used to invoke the image. For example:

    $ ECHO == "$DSK$:COMMARG.EXE"[Return]

The symbol ECHO is installed as a foreign command that invokes the image in COMMARG.EXE. The definition of ECHO must begin with a dollar sign ($) and include a device name, as shown.

For more information about the procedure for installing a foreign command, see the OpenVMS DCL Dictionary.

Example 1-1 shows a program called COMMARG.C, which displays the command-line arguments that were used to invoke it.

Example 1-1 Echo Program Using Command-Line Arguments

    /*  This program echoes the command-line arguments.            */

    #include <stdio.h>
    #include <stdlib.h>

    int main(int argc, char *argv[])
    {
       int i;
                                       /* argv[0] is program name  */
       printf("program: %s\n",argv[0]);

       for (i = 1;  i < argc;  i++)
          printf("argument %d: %s\n", i, argv[i]);

    exit (EXIT_SUCCESS);
    }

You can compile and link the program using the following DCL command lines:

    $ CC COMMARG[Return]
    $ LINK  COMMARG[Return]

A sample output for Example 1-1 follows:

    $ ECHO  Long  "Day's"  "Journey into Night"[Return]
    program: db7:[oneill.plays]commarg.exe;1
    argument 1: long
    argument 2: Day's
    argument 3: Journey into Night

DCL converts most arguments on the command line to uppercase letters. Compaq C internally parses and modifies the altered command line to make Compaq C argument access compatible with C programs developed on other systems. All alphabetic arguments in the command line are delimited by spaces or tabs. Arguments with embedded spaces or tabs must be enclosed in quotation marks (" "). Uppercase characters in arguments are converted to lowercase, but arguments within quotation marks are left unchanged.

# 1.7 64-bit Addressing Support (ALPHA ONLY)

OpenVMS Alpha 64-bit virtual addressing support makes the 64-bit virtual address space defined by the Alpha architecture available to the OpenVMS operating system and its users. It also allows per-process virtual addressing for accessing dynamically mapped data beyond traditional 32-bit limits.

This support is provided through command-line qualifiers and pragma preprocessor directives that control the size of the C pointer because:

- Typical C usage involves many objects accessed through pointers rather than single monolithic arrays or structures.
- Huge declared objects would have an impact on object-module format and the linker.

  Note Single objects larger than 2 gigabytes are not fully supported, even with 64-bit virtual addressing in effect.

- Minimal source-code edits are required to exploit the 64-bit space where needed. Because the pragmas affect a region of source code, it is not necessary to modify every declaration.

No changes are required for existing 32-bit applications that do not need to exploit 64-bit addressing.

## 1.7.1 Qualifiers and Pragmas

The following qualifiers, pragmas, and predefined macro control pointer size:

- /[NO]POINTER_SIZE={LONG | SHORT | 64 |32}
- /[NO]CHECK=[NO]POINTER_SIZE=(option,...)
- `#pragma pointer_size`
- `#pragma required_pointer_size`
- `__INITIAL_POINTER_SIZE` predefined macro

### 1.7.1.1 The /POINTER_SIZE Qualifier

The /POINTER_SIZE qualifier lets you specify a value of 64 or 32 (or LONG or SHORT) as the default pointer size within the compilation unit. You can compile one set of modules using 32-bit pointers and another set using 64-bit pointers. Take care when these two separate groups of modules call each other.

The default is /NOPOINTER_SIZE, which:

- Disables pointer-size features, such as the ability to use `#pragma pointer_size`
- Directs the compiler to assume that all pointers are 32-bit pointers.

This default represents no change over previous versions of Compaq C.

Specifying /POINTER_SIZE with a keyword value (32, 64, SHORT, or LONG) has the following effects:

- Enables processing of `#pragma pointer_size` .
- Sets the initial default pointer size to 32 or 64, as specified.
- Predefines the preprocessor macro `__INITIAL_POINTER_SIZE` to 32 or 64, as specified. If /POINTER_SIZE is omitted from the command line, `__INITIAL_POINTER_SIZE` is 0, which allows you to use `#ifdef __INITIAL_POINTER_SIZE` to test whether or not the compiler supports 64-bit pointers.
- For /POINTER_SIZE=64, the Compaq C RTL name mapping table is changed to select the 64-bit versions of `malloc` , `calloc` , and other RTL routines by default.

Use of the /POINTER_SIZE qualifier also influences the processing of Compaq C RTL header files:

- For those functions that have both 32-bit and 64-bit implementations, specifying /POINTER_SIZE enables function prototypes to access both functions, regardless of the actual value supplied to the qualifier. The value specified to the qualifier determines the default implementation to call during that compilation unit.
- Functions that require a second interface to be used with 64-bit pointers reside in the same object libraries and shareable images as their 32-bit counterparts. Because no new object libraries or shareable images are introduced, using 64-bit pointers does not require changes to your link command or link options files.

See the Compaq C Run-Time Library Reference Manual for OpenVMS Systems for more information on the impact of 64-bit pointer support on Compaq C RTL functions.

See Section 1.3.4 for more information about /POINTER_SIZE.

### 1.7.1.2 The __INITIAL_POINTER_SIZE Macro

The `__INITIAL_POINTER_SIZE` preprocessor macro is useful for header-file authors to determine:

- If the compiler supports 64-bit pointers.
- If the application expects to use 64-bit pointers.

Header-file code can then be conditionalized using the following preprocessor directives:

    #if defined (__INITIAL_POINTER_SIZE) /* Compiler supports 64-bit pointers */
    #if __INITIAL_POINTER_SIZE > 0       /* Application uses 64-bit pointers */
    #if __INITIAL_POINTER_SIZE == 32   /* Application uses some 64-bit pointers,
                                           but default RTL routines are 32-bit.*/

    #if __INITIAL_POINTER_SIZE == 64   /* Application uses 64-bit pointers and
                                           default RTL routines are 64-bit. */

### 1.7.1.3 The /CHECK=POINTER_SIZE Qualifier

Use the /CHECK=POINTER_SIZE qualifier to generate code that checks 64-bit pointer values at runtime to make sure they can fit in a 32-bit pointer. If such a value cannot be represented by a 32-bit pointer, the run-time code signals a range error (SS$_RANGEERR).

Be aware that the compiler generates the same kinds of warning messages for pointer-size mismatches whether or not this qualifier is specified. The run-time checks can detect problems that cannot be detected at compile time, and can help determine whether or not certain warnings are safe to suppress.

See Section 1.3.4 for more information about /CHECK=POINTER_SIZE, including defaults and an example.

### 1.7.1.4 Pragmas

The `#pragma pointer_size` and `#pragma required_pointer_size` preprocessor directives can be used to change the pointer size currently in effect within a compilation unit. You can default pointers to 32-bits and then declare specific pointers within the module as 64-bits. In this case, you also need to specifically call the `_malloc64` form of `malloc` to obtain memory from the 64-bit memory area.

These pragmas have the following format:

`#pragma pointer_size keyword #pragma required_pointer_size keyword`

The keyword is one of the following:

{ `short` |32} | 32-bit pointer
{ `long` |64} | 64-bit pointer
`save` | Saves the current pointer size
`restore` | Restores the current pointer size to its last saved state

The `#pragma pointer_size` and `#pragma required_pointer_size` directives work essentially the same way, except that `#pragma required_pointer_size` always takes effect regardless of command-line qualifiers, while `#pragma pointer_size` is only in effect when the /POINTER_SIZE command-line qualifier is used.

The `#pragma pointer_size` behavior allows a program to be built using 64-bit features as purely as a 32-bit program, just by changing the command-line qualifier.

The `#pragma required_pointer_size` is intended for use in header files where interfaces to system data structures must use a specific pointer size regardless of how the program is compiled.

See Sections 5.4.17 and 5.4.18 for more information on the pointer-size pragmas.

## 1.7.2 Determining Pointer Size

The pointer-size qualifiers and pragmas affect only a limited number of constructs in the C language itself. At places where the syntax creates a pointer type, the pointer-size context determines the size of that type. Pointer-size context is defined by the most recent pragma (or command-line qualifier) affecting pointer size.

Here are examples of places in the syntax where a pointer type is created:

- The * in a declaration or cast:

      int **p;  // Declaration
      ip = (int **)i;  // Cast

- The outer (leftmost) brackets [] in a formal parameter imply a *:

      void foo(int ia[10][20]) {}

      // Means the following:

      void foo(int (*ia)[20]) {}

- A function declarator as a formal parameter imply a *:

      void foo (int func()):

      // Means the following:

      void foo (int (*)() func);

- Any formal parameter of array or function type implies a *, even when bound in a `typedef` :

      typedef int a_type[10];

      void foo (a_type ia);

      // Means the following:

      void foo (int *ia);

Note that a `typedef` binds the meaning of pointer syntax while a macro does not. Even though both constructs can contain a * used in a declaration, the * in the macro definition is not affected by any pointer-size controls until the point at which the macro is expanded. For example:

    #pragma pointer_size 64
    typedef int * j_ptr;    // * is 64-bit
    #define J_PTR int *     // * is not analyzed

    #pragma pointer_size 32
    j_ptr j;   // j is a 64-bit pointer.
    J_PTR J;   // J is a 32-bit pointer.

### 1.7.2.1 Special Cases

The following special cases are not affected by pointer-size context:

- Formal parameters to `main` are always treated as if they were in a `#pragma pointer_size system_default` context, which is 32-bit pointers for OpenVMS systems.
  For example, regardless of the `#pragma pointer_size 64` directive, argv[0] is a 32-bit pointer:

      #pragma pointer_size 64

      main(int argc, char **argv)
        { ASSERT(sizeof(argv[0]) == 4); }

- A string literal produces a 32-bit pointer when used as an rvalue:

      #pragma pointer_size 64

      ASSERT(sizeof("x" + 0) == 4);

- The `&` operator yields a 32-bit pointer unless it is applied to pointer dereference, in which case it is the size of the dereferenced pointer type:

      sizeof(&foo) == 32

      sizeof(&s ->next) == sizeof(s)

- An rvalue cast to a 32-bit pointer type does not modify the high-order 32 bits of a 64-bit operand. `sizeof` yields 4 bytes, but the high bits are not lost unless a 4-byte assignment occurs:

      #pragma pointer_size 64
      typedef int * ip64;

      #pragma pointer_size 32
      typedef int * ip32;

      ip64 a,b;
      ip32 c;

      a = (ip32)b;   // No high-order bits are lost
      c = (ip32)b;   // High-order bits are lost

Previous | Next | Contents | Index

privacy and legal statement