[an error occurred while processing this directive]

HP OpenVMS Systems Documentation

Content starts here

HP Pascal for OpenVMS
Language Reference Manual


Previous Contents Index

A.2.4 Allocation Sizes of Variables

For every HP Pascal data type, the compiler calculates the allocation size required when a variable of the type occurs in either an unpacked or a packed context. The unpacked size is always represented in bytes, while the packed size is represented in bits.

The packed size of a variable is the minimum number of bits required to represent all values of the variable's type. In general, the compiler uses the following 32-bit rules to determine the allocation size for a component of a packed structured variable:

  • A component whose length is 32 bits or fewer is packed into as few bits as possible and can be unaligned.
  • A component whose length is greater than 32 bits is allocated the smallest number of bytes possible and must be at least byte aligned.

If one of the size attributes (BIT, BYTE, WORD, LONG, QUAD, or OCTA) is applied to the variable, the size specified by the attribute represents the variable's packed size. Objects of floating point or pointer types must have a size equal to their allocation size. Ordinal types cannot exceed their maximum size, which is determined by the platform and the value of the data switch for the compile command. If no size attribute is applied to the variable, the compiler calculates the unpacked size so that it is structurally compatible with the base type of the variable's type.

Storage for variables of type VARYING OF CHAR is allocated as one byte per character, with an initial field of two bytes to indicate the total length. Storage allocation for a variable of type VARYING OF CHAR whose maximum length is less than or equal to 32 bits follows the 32-bit rules in that the variable can be unaligned. On OpenVMS I64 and OpenVMS Alpha systems, variables of type VARYING OF CHAR that need alignment are aligned on a word boundary.

On OpenVMS VAX systems, variables of type VARYING OF CHAR that need alignment are aligned on a byte boundary.

Structured objects (ARRAY and RECORD) take their maximum alignment from their components, for example, if the largest object is a word, the structure is aligned on a word boundary.

The maximum size for any variable is 231-1 bits.

A.2.5 Storage Allocation of Types

Table A-6 shows the allocation size for variables of each type when the variables occur in either a packed or an unpacked context.

Table A-6 Storage Allocation of Types
Data Type Unpacked
Size in Bytes
Packed
Size in Bits
INTEGER
INTEGER32
UNSIGNED
UNSIGNED32
4 32
INTEGER64
UNSIGNED64
8 64
CHAR 1 8
BOOLEAN 1 or 4 1 1
Enumerated 2 1, if 256 elements or
fewer; 2, if more than
256 elements, or 4 1
log2(number of elements) 3 + 1
Subrange The size of the base type If either the upper or lower bounds contain a reference to a formal discriminant, then the size of the base type, otherwise the minimum number in which the upper and lower bounds can be expressed 4
REAL or SINGLE 4 32
DOUBLE 8 64
QUADRUPLE 16 128
Pointer (OpenVMS I64 and OpenVMS Alpha systems only) 4 or 8 5 32 or 64 5
Pointer (OpenVMS VAX systems only) 4 32
Unpacked
ARRAY
The sum of the unpacked sizes in bytes of all components, plus the sum of the sizes in bytes of any holes created to meet alignment requirements Unpacked size in bytes * 8
Unpacked
RECORD
The sum of the unpacked sizes in bytes of the fields in the fixed part and the largest variant, plus the sum of the sizes in bytes of any holes created to meet alignment requirements Unpacked size in bytes * 8
PACKED
ARRAY
The sum of the packed sizes in bits of all components, plus the sum of sizes in bits of any holes created to meet alignment requirements; this sum is rounded up to a multiple of 8 and then divided by 8 The sum of the packed sizes in bits of all components, plus the sum of sizes in bits of any holes created to meet alignment requirements; if the sum is greater than 32, the sum is rounded up to the next multiple of 8
PACKED
RECORD
The sum of the packed sizes in bits of all fields in the fixed part and the largest variant, plus the sum of sizes in bits of any holes created to meet alignment requirements; this sum is rounded up to a multiple of 8 and then divided by 8 The sum of the packed sizes in bits of all fields in the fixed part and the largest variant, plus the sum of sizes in bits of any holes created to meet alignment requirements; if the sum is greater than 32, the sum is rounded up to the next multiple of 8
STRING,
VARYING OF
CHAR
Maximum length + 2 (Maximum length + 2) * 8
Nonstatic
PACKED
SET,
Unpacked
SET 3
32, if the set base type is a subrange of INTEGER or UNSIGNED; else, compute (ORD(upper-bound of ordinal type that is base type of set's base type) + 8) DIV 8, and if this result is less than or equal to 8, the result is rounded up to 1, 2, 4, or 8 Compute (ORD (upper-bound) + 1); if the result is less than or equal to 64, the result is rounded up to 8, 16, 32, or 64, and if the result is greater than 64, the result is rounded to next higher multiple of 8
PACKED SET 3 The result of (ORD(upper-bound) + 8) DIV 8 Compute (ORD (upper-bound) + 1); if the result is greater than 32, the result is rounded to next higher multiple of 8
FILE Not specified Not specified

1It depends on the value specified for the /ENUMERATION_SIZE qualifier.
2The maximum number of elements is 65,535.
3This is known as the ceiling function, where the smallest integer is greater than or equal to X.
4Sets of type INTEGER and UNSIGNED are limited to 256 bits.
5By default, pointers on OpenVMS I64 and OpenVMS Alpha systems are 32 bits in size. However, the QUAD attribute can be used on pointer declarations to specify 64-bit pointers. See the HP Pascal for OpenVMS User Manual for more information.

The formula to compute the size of a packed subrange is MAX (X,Y) + Z where X, Y, and Z are computed as follows (LOW represents the low bound of the subrange; HIGH represents the upper bound):


        IF LOW < -1                     IF HIGH> 0
        THEN                            THEN
           X := log2(-LOW - 1) + 1         Y := log2(HIGH) + 1
        ELSE                            ELSE
           X := 0;                         Y := 0;

        IF LOW >= 0
        THEN
           Z := 0
        ELSE
           Z := 1;

You can discover both the unpacked and packed sizes for variables of any type by using the predeclared functions BITNEXT, BITSIZE, NEXT, and SIZE, which require a parameter that is the name of either a type or a variable. These functions return the following integer values:

  • BITNEXT returns an integer value that indicates what the packed size would be for an array component of the type.
  • BITSIZE returns an integer value that indicates what the packed size would be for a record field of the type.
  • NEXT returns an integer value that indicates what the unpacked size would be for an array component of the type.
  • SIZE returns an integer value that indicates what the unpacked size would be for a variable or record field of the type.

The maximum size for any variable is 231-1 bits.

For More Information:

A.2.6 Allocation Size Examples

The following examples show the effects of packing records and multidimensional arrays at various levels.

Note

Although packing records and arrays does save storage space and can be necessary for compatibility with other code, note that accessing unaligned variables on an OpenVMS I64 or OpenVMS Alpha system takes many more instructions than accessing variables with natural alignment, such as those in unpacked records and arrays.

Example 1


TYPE
   Internal_Arr = ARRAY[1..5] of 0..6;

VAR
   Samp1_Arr : PACKED ARRAY[1..5] OF Internal_Arr;

Each component of an array of type Internal_Arr is stored in a longword. Each component of Samp1_Arr, in turn, requires five longwords, which is enough storage space for five components of type Internal_Arr. The entire array Samp1_Arr occupies 25 longwords (800 bits).

Example 2


VAR
   Samp1_Arr : ARRAY[1..5] OF PACKED ARRAY[1..5] OF 0..6;

Each PACKED ARRAY[1..5] of 0..6 requires 15 bits (the range 0..6 requires 3 bits; five 3-bit components requires 15 bits). Because the packed arrays are components of an unpacked array, their size is rounded up to an even 16 bits. The total size of Samp1_Arr is 80 bits.

Example 3


TYPE
   Internal_Arr = PACKED ARRAY[1..5] OF 0..6;

VAR
   Samp2_Arr : PACKED ARRAY[1..5] OF Internal_Arr;
   Samp3_Arr : PACKED ARRAY[1..5,1..5] OF 0..6;

In this example, every component of Internal_Arr requires only three bits because the array is packed. Each component of Samp2_Arr and Samp3_Arr can be stored in 15 bits, and each array occupies 75 bits. The specification of PACKED for an array with multiple indexes results in packing at every level. The two arrays in this example are equivalent.

Example 4


VAR
   Sample : PACKED ARRAY[1..5,1..5,1..5] OF 0..6;

This example shows space savings for arrays of more than two dimensions when PACKED is specified at every level. The subrange 0..6 requires 3 bits; five 3-bit components require 15 bits. This size describes the innermost dimension of Sample. Next, five 15-bit components require 75 bits. Because of the 32-bit rules, each 75-bit component is rounded up to 80 bits. This size describes the middle and inner dimensions of Sample. Finally, five80-bit components require 400 bits (50 bytes). The entire array Sample then requires 400 bits.

Example 5


VAR
   Sample_Rec : PACKED RECORD
                   Field_1 : BOOLEAN;
                   Field_2 : INTEGER32;
                   Field_3 : DOUBLE;
                END;

In this example, Field_1 requires only 1 bit of storage. Field_2 is 32 bits in size (declared as INTEGER32) and starts immediately following Field_1. Because Field_3 is larger than 32 bits, it will start on the next byte boundary. The entire record Sample_Rec, therefore, requires 104 bits.

A.2.7 Alignment Boundaries

The memory-addressing boundary on which a variable or a component is aligned depends on the variable's or the component's allocation size. You can change the alignment by using the ALIGNED and UNALIGNED attributes. Table A-7 lists the conditions that determine boundary alignment.

Table A-7 Conditions Determining Boundary Alignment
Object Arguments to the Alignment Switch
  NATURAL1 VAX
Variable declared with an alignment attribute Specified alignment Specified alignment
Variable declared without an alignment attribute Natural alignment Byte alignment 2
Component of an unpacked array or record variable Natural alignment Byte alignment
Component of a packed array or record variable Follows the 32-bit rules 3 Follows the 32-bit rules 4
Dynamic variables allocated by the NEW procedure Octaword alignment on OpenVMS I64; quadword alignment on OpenVMS Alpha Quadword alignment

1Previous versions of HP Pascal used ALPHA_AXP for this keyword. The NATURAL keyword is now the recommended spelling for the same behavior. The ALPHA_AXP keyword will continue to be recognized for compatibility with old source files.
2The compiler can align such variables on a larger storage boundary if it can access them more efficiently by doing so.
3If a variable of type VARYING OF CHAR on an OpenVMS I64 or OpenVMS Alpha system requires alignment, it is aligned on a word boundary.
4If a variable of type VARYING OF CHAR on an OpenVMS VAX system requires alignment, it is aligned on a byte boundary.

You can save storage space by packing variables of structured types, but you must be careful to pack at the proper level. Except for its alignment, a record field whose type is an unpacked array, set, or record occupies the same amount of space in a packed or an unpacked record variable. To pack such a field, you must explicitly declare its type to be packed.

When packing multidimensional arrays, you must specify packing at the innermost level to gain any significant space advantage. For example, there is no advantage in packing an array of an unpacked structured type; the unpacked components will still be aligned on byte boundaries, which leaves holes in the storage space. To gain storage space, you must specify a packed array of a packed structured type.

The following examples show the use of alignment boundaries.

Note

Although packing records and arrays does save storage space and can be necessary for compatibility with other code, note that accessing unaligned variables on an OpenVMS I64 or OpenVMS Alpha system takes many more instructions than accessing variables with natural alignment, such as those in unpacked records and arrays.

Example 1


VAR
   X : [STATIC, ALIGNED(3)] INTEGER;  { QUADWORD ALIGNED }
                                      { $SDATA$ on OpenVMS I64 }
                                      { $DATA$ on OpenVMS Alpha }
                                      { $LOCAL on OpenVMS VAX }

In this example, X is declared a static variable that is aligned on a QUADWORD boundary.

Example 2


VAR
   X : PACKED RECORD                   { AUTOMATIC }
          Field1 : BOOLEAN;
          Field2 : REAL;
          Field3 : BOOLEAN;
          Field4 : DOUBLE;
       END;

In this example, Field1 begins at bit position 0 and is 1 bit long. Field2 begins at bit position 1 and is 32 bits long. Field3 begins at bit position 33 and is 1 bit long. However, because Field4 is greater than 32 bits long (DOUBLE requires 64 bits) Field4 must be byte aligned. For this reason, Field4 begins on bit position 40 and is 64 bits long.

Example 3


VAR
   X : RECORD                        { AUTOMATIC }
          Field1 : [BIT(3)]  0..7;
          Field2 : [UNALIGNED] INTEGER32;
       END;

In this example, Field1 of record X is declared to begin on bit position 0 and is 3 bits long. Due to the use of the UNALIGNED attribute on Field2, Field2 begins on bit position 3 and is 32 bits long. You can obtain the same behavior by packing record X.

Without using the UNALIGNED attribute, or without X being a PACKED record, Field2 would have been longword aligned; that is, it would have started on bit position 32. You cannot use the UNALIGNED attribute with INTEGER64 because of the 32-bit rules, which states that variables greater than 32 bits must be at least byte-aligned.

For More Information:

A.3 Internal Representation of Data Types

The following sections summarize the internal representation of the
HP Pascal data types.

A.3.1 Representation of Varying Data

This section summarizes the internal representation of VARYING OF CHAR types. A variable of type VARYING OF CHAR is stored as though it were an HP Pascal record type of the following form:


RECORD
   Length : [WORD] 0..Maxlength;
   Body : PACKED ARRAY[1..Maxlength] OF CHAR;
END;

Figure A-1 shows the storage allocated for a variable of type VARYING[8] OF CHAR.

Figure A-1 Storage of Varying Data


The predefined schema type STRING uses VARYING OF CHAR as its underlying data type, so Figure A-1 also represents the STRING type.

For More Information:

A.3.2 Representation of Floating-Point Data

The following sections summarize the internal representation of single-precision (F_floating and S_floating), double-precision (D_floating, G_floating, and T_floating), and quadruple-precision (H_floating and X_floating) floating-point numbers.

For More Information:

A.3.2.1 F_floating-Point Numbers

An F_floating-point value is represented by four contiguous bytes. The bits are numbered from the right, 0 through 31, as shown in Figure A-2.

Figure A-2 F_floating-Point Data Representation


An F_floating-point value is specified by its address A, the address of the byte containing bit 0. The form of this value is sign magnitude as follows:

  • Bit 15 is the sign bit.
  • Bits 14 through 7 are an excess 128 binary exponent.
  • Bits 6 through 0 and 31 through 16 are a normalized 24-bit fraction with the redundant most significant fraction bit not represented. Within the fraction, bits of increasing significance go from 16 through 31 and from0 through 6.

For More Information:

A.3.2.2 S_floating-Point Numbers

An S_floating-point value is represented by four contiguous bytes. The bits are numbered from the right, 0 through 31, as shown in Figure A-3.

Figure A-3 S_floating-Point Data Representation


An S_floating-point value is specified by its address A, the address of the byte containing bit 0. The form of this value is sign magnitude as follows:

  • Bit 31 is the sign bit (0 for positive numbers, 1 for negative numbers).
  • Bits 30 through 23 are an excess 127 exponent.
  • Bits 22 through 0 are a normalized 24-bit fraction with the redundant most significant fraction bit not represented.

For More Information:


Previous Next Contents Index