United States    
COMPAQ STORE | PRODUCTS |
SERVICES | SUPPORT | CONTACT US | SEARCH
cxxtitle.gif (12116 bytes)
Compaq C++

Compaq C++
Using Compaq C++ for Tru64 UNIX Systems


Previous Contents Index

3.5 Using 32-bit Pointers (xtaso)

Normally, Compaq C++ uses 64 bits for all pointers in generated code. The eXtended Truncated Address Support Option (xtaso), and other #pragma directives and compiler options, let code with 32-bit pointers coexist within this 64-bit operating system environment. Such a capability can be useful when the data layout used for pointers must be compatible with the layout on a 32-bit processor.

The 32-bit pointer data type lets application developers minimize the amount of memory used by dynamically allocated pointers. Using 32-bit pointers can sometimes improve performance if the volume of data occupied by pointers is large. In certain instances, the capability can be helpful in porting applications that contain assumptions about pointer sizes, although the following precautions apply:

To use 32-bit pointers, you must use a combination of #pragma preprocessor directives and command-line compiler options. These #pragmas are described in Section 2.2.1 and are summarized in the following table:
pragma Directive Description
pointer_size Controls the pointer size of all pointers except virtual function and virtual base pointers in a C++ class object.

Has an effect only if you specify one or more of the pointer-size compiler options.

required_pointer_size Has the same effect as #pragma pointer_size but is always enabled, whether or not you specify any pointer-size compiler options.
required_vptr_size Controls the size of virtual function and virtual base pointers in a C++ class object.

Always enabled, whether or not you specify any pointer size compiler options.

The pointer size compiler options are -xtaso, -xtaso_short, -vptr_size, and -vptr_size_short. Whenever any of these options are specified on the command line, the following actions occur:

Additionally, the pointer size options individually have following effects:
Compiler Option Description
-xtaso Sets the default pointer size of the compilation unit to 64 bits (for all pointers except virtual function and virtual base pointers in a C++ class object). This is the normal default unless overridden by -xtaso_short .
-xtaso_short Sets the default pointer size of the compilation unit to 32 bits (for all pointers except virtual function and virtual base pointers in a C++ class object).
-vptr_size Makes 64 bits the default size of virtual function and virtual base pointers in a C++ class object. This is the normal default unless overridden by -vptr_size_short .
-vptr_size_short Makes 32 bits the default size of virtual function and virtual base pointers in a C++ class object.

Note that you cannot reset the size of the this pointer. The this pointer always remains the system default pointer size, which is 64 bits.

When using these #pragma directives and compiler options, you must take particular care if you call functions in any library compiled with different pointer sizes. The approaches that you can use to mix 32- and 64-bit pointers are as follows:

  1. Make 64 bits the default pointer size and use 32-bit pointers for particular declarations.
  2. Make 32 bits the default pointer size.

The second approach generally is more difficult because of problems in combining your code with code that expects 64-bit pointers. The sections that follow discuss these approaches in more detail.

Approach 1: Making 64 bits the default pointer size

With this approach, most pointers in your application are 64 bits, and 32 bits are used for selected pointers. To use this approach, you must compile with -xtaso to enable #pragma pointer_size and cause the cxx command to pass -taso to the linker. In addition, you use #pragma pointer_size, #pragma required_pointer_size, and #pragma required_vptr_size to control the pointer sizes for particular declarations. For example, to save space in an object, you can declare a class as follows:


#pragma pointer_size save 
#pragma required_vptr_size save 
#pragma pointer_size short 
#pragma required_vptr_size long 
        class Table_Node { 
                char *table;    // 32-bit pointers 
                Table_Node *next; 
                Table_Node *(Table_Node::*search)(char *); 
                                // pointer to member has 
                                // 2 32-bit fields 
        public: 
#pragma pointer_size long 
                void insert_node(char *); 
                Table_Node *extract_node(char *); 
                Table_Node *search_forward(char *); 
                Table_Node *search_backward(char *); 
        }; 
#pragma pointer_size restore 
#pragma required_vptr_size restore 

With this approach, you must take care to specify the pointer size #pragma directives after any #include directives, so that header files that assume 64-bit pointer sizes are not affected.

Approach 2: Making 32 bits the default pointer size

To use this approach, compile using the -xtaso_short and -vptr_size_short options on the cxx command. With this approach, the default pointer size is 32 bits; you must take care when interfacing to code that expects 64-bit pointers.

Specifically, you must protect header files so that the pointer size assumptions made in compiling the header file are the same as those made when the associated code was compiled. None of the system header files, including those for the standard C library, are protected. For more information, see Section 3.5.1.

Regardless of which approach you use, you must take particular care when passing any data that contains pointers (for example, an array of pointers or a struct that contains pointers) to be sure that the pointer size is the same as expected by the called function.

Compaq C++ does not permit overloading based on pointer sizes. To minimize problems, you should declare functions, including member functions with long pointer sizes. During calls to such functions, Compaq C++ promotes short pointers to long pointers.

3.5.1 Protecting Header Files When Using -xtaso_short

When compiling with the -xtaso_short option, you must protect header files so that pointer size assumptions that are made when the header file is included into a compilation unit using the #include directive are the same as those made when the code associated with the header file was compiled.

None of the system header files are protected. Thus, most programs will not work correctly when compiled with the -xtaso_short option, unless you protect the system header files and any other header files associated with code that assumes 64-bit pointers.

To provide the necessary protection you can one of the following:

If you choose to modify each header file needing protection, you can use the #pragma environment directive, as in the following example:


#pragma __environment save              // Save pointer size 
#pragma __environment header_defaults   // set to system defaults 
 
// existing header file 
 
#pragma__environment restore            // Restore pointer size 

See Section 2.2.1.2 for more information about using this pragma.

Header File Protection Option

With this option, you can place special header files in a directory. Compaq C++ processes these special header files before and after each file included with the #include directive from this directory. These special header files are named:

The compiler checks for files with these special names when processing #include directives. If the special prologue file exists in the same directory as a file with the #include directive, the contents of the prologue file are processed just before the file included with the #include directive. Similarly, if the epilogue file exists in the same directory as the file included with the #include directive, it is processed just after that file.

For convenience, you can protect header files using the script supplied in the following directory:


/usr/lib/cmplrs/cxx/protect_system_headers.sh 

This script creates, in all directories in a directory tree that contain header files, symbolic links to special header prologue and epilogue files.

The default directory tree root assumed by the script is /usr/include, but you can specify other roots.

3.6 Hints for Designing Upwardly Compatible C++ Classes

If you produce a library of C++ classes and expect to release future revisions of your library, you should consider the upward compatibility of your library. Having your library upwardly compatible makes upgrading to higher versions of your library easier for users. And if you design your library properly from the start, you can accomplish upward compatibility with minimal development costs.

The levels of compatibility discussed in this section are as follows:

  1. Source compatibility
  2. Link compatibility
  3. Run or binary compatibility

The format in which your library ships determines the levels of compatibility that apply:
If you ship your library in ... The following apply:
Source format Source compatibility only
Object format Source and link compatibility
Shareable library format All three kinds of compatibility

If you break compatibility between releases, you should at least document the incompatible changes and provide hints for upgrading between releases.

3.6.1 Source Compatibility

Achieving source compatibility means that users of your library will not have to make any source code changes when they upgrade to your new library release. Their applications will compile cleanly against your updated header files and will have the same run-time behavior as with your previous release.

To maintain source compatibility, you must ensure that existing functions continue to have the same semantics from the user's standpoint. In general, you can make the following changes to your library and still maintain source compatibility:

3.6.2 Link Compatibility

Achieving link compatibility means that users of your library can relink an application against your new object or shareable library and not be required to recompile their sources.

What can change

To maintain link compatibility, the internal representation of class objects and interfaces must remain constant. In general, you can make the following changes to your library and still maintain link compatibility:

What cannot change

Because the user may be linking object modules from your previous release with object modules from your new release, the layout and size of class objects must be consistent between releases. Any user-visible interfaces must also be unchanged; even the seemingly innocent change of adding const to an existing function will change the mangled name and thus break link compatibility.

The following are changes that you cannot make in your library:

Designing Your C++ Classes for Link Compatibility

Although the changes you are allowed to make in your library are severely restricted when you aim for link compatibility, you can take steps to prepare for this and thereby reduce the restrictions. Compaq suggests using one of the following design approaches:

3.6.3 Run Compatibility

Achieving run compatibility means that users of your library can run an application against your new shareable library and not be required to recompile or relink the application.

This requires that you follow the guidelines for link compatibility as well as any operating system guidelines for shareable libraries. For example, you need to ensure your version identifier is upwardly compatible between releases. Refer to the reference pages for ld for information on creating a shareable library.

3.6.4 Additional Reading

The C++ Programming Language, 2nd Edition offers some advice on compatibility issues; the information is sprinkled throughout the book, but a good summary can be found at the end of section 5.3.1. Another good reference is Designing and Coding Reusable C++, Chapter 7, by Martin D. Carroll and Margaret E. Ellis.


Chapter 4
Porting to Compaq C++

Compaq C++ implements the C++ language as defined in The Annotated C++ Reference Manual, and closely follows that text's language definition.

This chapter describes ways to avoid having the Compaq C++ compiler reject program code that previously worked with other C++ implementations that adhere less strictly to the C++ language definition. References to applicable portions of The C++ Programming Language, 2nd Edition indicate where you can find additional help.

For compatibility with certain C++ compilers, Compaq C++ supports the -cfront and -ms options to the cxx command. These option direct the compiler to interpret the source program according to certain rules followed by other implementations of the C++ language. For more information, see Section 2.1.

4.1 Using Classes

This section discusses porting issues pertaining to C++ classes.

4.1.1 Friend Declarations

When making friend declarations, use the elaborated form of type specifier. The following code fragment implements the legal and comments out the illegal friend declaration:


class Y; 
class Z; 
class X; 
   //friend Y;  ** not legal 
   friend class Z; // legal 
};      

4.1.2 Member Access

Compaq C++ enforces accessibility rules for public, protected, and private members of a base class. For more information, see §r.11.2 of The C++ Programming Language, 2nd Edition.

4.1.3 Base Class Initializers

Unlike some older C++ implementations, Compaq C++ requires you to use the base class name in the initializer for a derived class. The following code fragment implements a legal initializer and comments out an illegal initializer:


class Base { 
    // ...
public: 
    Base (int); 
}; 
class Derived : public Base { 
    // ...
public: 
    // Derived(int i) : (i)  {/* ...*/}    ** not legal        
    Derived(int i) : Base(i) {/* ...*/} // ** legal, supplies class name 
}; 

For more information, see §r.12.6.2 and §r.18.3.2 of The C++ Programming Language, 2nd Edition.

4.2 Undefined Global Symbols for Static Data Members

When a static data member is declared, the Compaq C++ compiler issues a reference to the external identifier in the object code, which must be resolved by a definition. On Tru64 UNIX systems, the Compaq C++ compiler does not support the declaration anachronism shown in §r.18.3 of The C++ Programming Language, 2nd Edition.

For example, consider the following code fragment:


 
int main () 
{ 
    int x; 
    x=C::i; 
    return 0; 
} 

The Compaq C++ compiler does not issue any messages during compilation; however, when you attempt to link a program containing this code, the linker issues a message similar to the following:


ld: 
Error: Undefined: 
i__1C 

4.3 Functions and Function Declaration Considerations

Compaq C++ requires the use of function definitions as described in §r.8.3 of The C++ Programming Language, 2nd Edition. For examples of outdated syntax not allowed in Compaq C++, see §r.18.3.1 of The C++ Programming Language, 2nd Edition.

Because all linkage specifications for a name must agree, function prototypes are not permitted if the function is later declared as an inline function. The following code is an example of such a conflicting function declaration:


int f(); 
inline int f() { return l; } 

In this example, f is declared with both internal and external linkage, which causes a compiler error.

Similarly, the declaration int f(i,j) causes an error even when the declaration is defined with the "C" linkage specification, because the linkage specification has no effect on the semantics of the declaration.

4.4 Using Pointers

This section demonstrates how to use pointers effectively in Compaq C++.

4.4.1 Pointer Conversions

In Compaq C++, you cannot implicitly convert a const pointer to a nonconstant pointer. For example, char * and const char * are not equivalent; explicitly performing such a cast can lead to unexpected results.

For more information, see §r.4.6 of The C++ Programming Language, 2nd Edition.

4.4.2 Bound Pointers

Binding a pointer to a member function with a particular object as an argument to the function is not allowed in Compaq C++. For more information on the illegality of casting bound pointers, see §18.3.4 of The C++ Programming Language, 2nd Edition.


Previous Next Contents Index
  

1.800.AT.COMPAQ

privacy and legal statement