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

2.2.3 Translation Limits

The only translation limits imposed in Compaq C++ are as follows:
Limit Meaning
32,767 Characters in an internal identifier or macro name.
32,767 Characters in a logical or physical source line.
32,767 Bytes in the representation of a string literal. This limit does not apply to string literals formed by concatenation.
32,767 Significant characters in an external identifier. A warning is issued if such an identifier is truncated.
1024 Arguments in a function call. 1
1024 Parameters in a function definition. 1
1012 Bytes in any one function argument.


1The compiler may add one or two hidden arguments to a function, which reduces to 1023 or 1022 the number of arguments available to the user.

2.2.4 Numerical Limits

The numerical limits, as defined in the header files <limits.h> and <float.h>, are as follows:

Numerical limits not described in this list are defined in The Annotated C++ Reference Manual.

2.2.5 Argument-Passing and Return Mechanisms

Compaq C++ passes arrays, functions, and class objects with a constructor or destructor by reference. All other objects are passed by value.

If a class has a constructor or a destructor, it is not passed by value. In this case, the compiler calls a copy constructor to copy the object to a temporary location, and passes the address of that location to the called function.

If the return value of a function is a class that has defined a constructor or destructor or is greater than 64 bits, storage is allocated by the caller and the address to this storage is passed in the first parameter to the called function. The called function uses the storage provided to construct the return value.

2.3 Implementation Extensions and Features

This section describes the extensions and implementation-specific features of Compaq C++ for Tru64 UNIX systems. Where appropriate, section numbers shown in parentheses in the headings (for example, §3.4) refer to relevant sections in the reference manual portion of The C++ Programming Language, 2nd Edition.

2.3.1 Identifiers (§r.2.3)

In Compaq C++, the dollar sign ($) is a valid character in an identifier.

For each external function with C++ linkage, the compiler decorates the function name with a representation of the function's type.

2.3.1.1 External Name Encoding

The Compaq C++ compiler uses the external name encoding scheme described in §7.2.1c of The Annotated C++ Reference Manual, with certain modifications. These modifications are necessary so that the encoding scheme does not depend on case distinction in linker names.

For the basic types, the external name encoding scheme is exactly the same as that described in The Annotated C++ Reference Manual, as follows:
Type Encoding
void v
char c
short s
int i
long l
float f
double d
long double r
... e

Class names are encoded as described in The Annotated C++ Reference Manual, except that the Compaq C++ compiler uses the lowercase q instead of uppercase Q, and denotes the qualifier count as a decimal number followed by an underscore, as follows:
Class Notation Encoding
simple Complex 7Complex
qualified X::YY q2_1x2yy

Type modifiers are encoded as follows:
Modifier Encoding
const k
signed g
volatile w
unsigned u
__unaligned b

Type declarators are encoded as follows:
Type Notation Encoding
array [10] a10_
function () x
pointer * p
pointer to member S::* m1S
reference & n
unnamed enumeration type h

On Tru64 UNIX systems, Compaq C++ also supports the following data types:
Type Encoding
__int16 ji4
__int32 ji5
__int64 ji6
__s_float js
__t_float jt

2.3.1.2 Character Limit for Long Names

If an external name has more than 1022 characters, the Compaq C++ compiler truncates the name to 1022 characters. The compiler keeps the first 1015 characters intact, reduces (hashes) the remaining characters to a string of 7 characters, and appends the 7 hashed characters to the first 1015.

2.3.2 Order of Static Object Initialization (§r.3.4)

Static objects are initialized in declaration order within a compilation unit and in link order across compilation units.

2.3.3 Integral Conversions (§r.4.2)

When demoting an integer to a signed integer, if the value is too large to be represented, the result is truncated and the high-order bits are discarded.

Conversions between signed and unsigned integers of the same size involve no representation change.

2.3.4 Floating-Point Conversions (§r.4.3 and §r.4.4)

When converting an integer to a floating-point number that cannot exactly represent the original value, Compaq C++ rounds off the result of the conversion to the nearest value that can be represented exactly.

When the result of converting a floating-point number to an integer or other floating-point number at compile time cannot be represented, the Compaq C++ compiler issues a diagnostic message.

When converting an integral number or a double floating-point number to a floating-point number that cannot exactly represent the original value, Compaq C++ rounds off the result to the nearest value of type float.

When demoting a double value to float, if the converted value is within range but cannot exactly represent the original value, Compaq C++ rounds off the result to the nearest representable float value.

Compaq C++ performs similar rounding for demotions from long double to double or float.

2.3.5 Explicit Type Conversion (§r.5.2.3)

In Compaq C++, the expression T() (where T is a simple type specifier) creates an rvalue of the specified type, whose value is determined by default initialization. According to The C++ Programming Language, 2nd Edition, the behavior is undefined if the type is not a class with a constructor, but the ANSI working draft removes this restriction. With this change you can now write:


    int i=int(); // i must be initialized to 0 

2.3.6 The sizeof Operator (§r.5.3.2)

The type of the sizeof operator is size_t. In the header file <stddef.h>, this type is defined as unsigned long, which is the type of the integer that holds the maximum size of an object.

2.3.7 Explicit Type Conversion (§r.5.4)

A pointer takes up the same amount of memory storage as objects of type long (or the unsigned equivalent). Therefore, a pointer can convert to any of these types and back again without changing its value. No scaling occurs and the representation of the value is unchanged.

Conversions to and from a shorter integer and a pointer are similar to conversions to and from a shorter integer and unsigned long. If the shorter integer type was signed, conversion fills the high-order bits of the pointer with copies of the sign bit.

2.3.8 Multiplicative Operators (§r.5.6)

The semantics of the division (/) and remainder (%) operator are as follows:

In the following cases of undefined behavior detected at compile time, the Compaq C++ compiler issues a warning:

2.3.9 Additive Operators (§r.5.7)

You can subtract pointers to members of the same array. The result is the number of elements between the two array members, and is of type ptrdiff_t. In the header file <stddef.h>, Compaq C++ defines this type as long.

2.3.10 Shift Operators (§r.5.8)

The expression E1 >> E2 shifts E1 to the right E2 positions. If E1 has a signed type, Compaq C++ fills the vacated high-order bits of the shifted value E1 with a copy of E1's sign bit (arithmetic shift).

2.3.11 Equality Operators (§r.5.10)

When comparing two pointers to members, the Compaq C++ compiler guarantees equality if either of the following conditions hold:

When comparing two pointers to members, the Compaq C++ compiler guarantees inequality if either of the following conditions hold:

When created by different address expressions, two pointers to members may compare either as equal or as unequal if they produce the same member when applied to the same object.

2.3.12 Type Specifiers (§r.7.1.6)

For variables that are modifiable in ways unknown to the Compaq C++ compiler, use the volatile type specifier. Declaring an object to be volatile means that every reference to the object in the source code results in a reference to memory in the object code.

2.3.13 asm Declarations (§r.7.3)

In Compaq C++, asm declarations produce a compile-time error.

2.3.14 Linkage Specifications (§r.7.4)

Specifying linkage other than "C++" or "C" generates a compile-time error.

In object files, Compaq C++ decorates with type information the names of functions with C++ linkage. This permits overloading and provides rudimentary type checking across compilation units. The type-encoding algorithm used is similar to that given in §7.2.1c of The Annotated C++ Reference Manual (see Section 2.3.1.1).

2.3.15 Class Layout (§r.9.2)

The alignment requirements and sizes of structure components affect the structure's alignment and size. A structure can begin on any byte boundary and can occupy any integral number of bytes.

2.3.15.1 Structure Alignment

Structure alignment represents the maximum alignment required by any member within the structure. When the structure or union is a member of an array, padding is added to ensure that the size of a record, in bytes, is a multiple of its alignment.

Components of a structure are laid out in memory in the order in which they are declared. The first component has the same address as the entire structure. Padding is inserted between components to satisfy alignment requirements of individual components.

2.3.15.2 Bit-Fields

The presence of bit-fields causes the alignment of the whole structure or union to be at least the same as that of the bit-field's base type.

For bit-fields (including zero-length bit-fields) not immediately declared following other bit-fields, their base type imposes the alignment requirements (less than that of type int). Within the alignment unit (of the same size as the bit-field's base type), bit-fields are allocated from low order to high order. If a bit-field immediately follows another bit-field, the bits are packed into adjacent space in the same unit, if sufficient space remains; otherwise, padding is inserted at the end of the first bit-field and the second bit-field is put into the next unit.

Bit-fields of base type char must be smaller than 8 bits. Bit-fields of base type short must be smaller than 16 bits.

2.3.15.3 Access Specifiers

The layout of a class is unaffected by the presence of access specifiers.

2.3.15.4 Class Subobject Offsets

A class object that has one or more base classes contains instances of its base classes as subobjects. The offsets of nonvirtual base class subobjects are less than the offsets of any data members that are not part of base class subobjects.

The offsets of nonvirtual base classes increase in derivation order. The offset of the first nonvirtual base class subobject of any class is 0. For single inheritance, the address of a class object is always the same as the address of its base class subobject.

If a class has virtual functions, an object of that class contains a pointer to a virtual function table (VFPTR). If a class has virtual base classes, an object of that class contains a pointer to a virtual base class table (VBPTR). For a class with no base classes, the offset of a VFPTR or VBPTR is greater than the offset of any data members. Thus, the offset of the first data member of a class with no base classes is 0, which facilitates interoperability with other languages. If the leftmost base class of a class with base classes has a VFPTR, a VBPTR, or both, and is not virtual, the class and its base class share the table or tables.

The offsets of virtual base class subobjects are greater than the offset of any data member, and increase in the order of derivation of the virtual base classes. In increasing order, a class object contains the following:

  1. Nonvirtual base class subobjects
  2. Data members
  3. VFPTR (if required)
  4. VBPTR (if required)
  5. Virtual base class subobjects

Consider the following example:


class B1 
{ 
 int x[1]; 
}; 
class B2 : virtual B1 
{ 
 int y[2]; 
 virtual int fl(); 
}; 
class B3 : virtual B2, virtual B1 
{ 
 int z[3]; 
 virtual int f2(); 
}; 
class D : B3 
{ 
 int a[4]; 
 virtual int f1(), f2(), f3(); 
}; 

Figure 2-1 shows the layout of an object of D class for this example.

Figure 2-1 Layout of an Object of D Class


2.3.16 Multiple Base Classes (§r.10.1)

Within a class object, base class subobjects are allocated in derivation order; that is, immediate base classes are allocated in the order in which they appear in the class declaration.

2.3.17 Temporary Objects (§r.12.2)

Under the following conditions, the compiler creates temporary objects for class objects with constructors:

Variations in the compiler generation of such temporary objects can adversely affect their reliability in user programs. The compiler avoids introducing a temporary object whenever it discovers that the temporary object is not needed for accurate compilation. Therefore, you should modify or write your programs so as not to depend on side effects in the constructors or destructors of temporary objects.

2.3.17.1 Lifetime of Temporary Objects

Generally Compaq C++ implements destruction of temporary objects at the ends of statements. In certain situations, however, temporary objects are destroyed at the end of the expression; they do not persist to the end of the statement. Temporary objects do not persist to the ends of statements in expressions that are:

Consider the following example:


struct A { 
  void print(int i); 
  A(); 
  ~A() { } 
}; 
 
struct B { 
  A* find(int i); 
  B(int i); 
  B(); 
  ~B() { } 
}; 
 
void f() { 
  B(8).find(6)->print(6); 
  (*(B(5).find(3))).print(3); 
  return; 
} 

In the first and second statements inside void f(), Compaq C++ destroys the temporary object, created in evaluating the expressions B(8) and B(5), after the call to A::print(int).


Previous Next Contents Index
  

1.800.AT.COMPAQ

privacy and legal statement