HP 3000 Manuals

Aligning Structures between Architectures [ HP C Programmer's Guide ] MPE/iX 5.0 Documentation


HP C Programmer's Guide

Aligning Structures between Architectures 

Differences in data type alignment can cause problems when porting code
or data between systems that have different alignment schemes.  For
example, if you write a C program on the Series 300/400 that writes
records to a file, then read the file using the same program on a Series
700/800, it may not work properly because the data may fall on different
byte boundaries within the file because of alignment differences.

Three methods can be used for aligning data within structures so that it
can be shared between different architectures.

   *   Use only ASCII formatted data.  This is the safest method, but has
       negative performance and space implications.

   *   Use the HP_ALIGN pragma, which is available on most HP-UX HP C
       compilers.  It forces a particular alignment scheme, regardless of
       the architecture on which it is used.  See "The HP_ALIGN pragma"
       section for a detailed description of this pragma.

   *   Define platform independent data structures using explicit
       padding.

To illustrate the portability problem raised by different alignments,
consider the following example.

     #include <stdio.h>
     struct char_int
       {
         char field1;
         int  field2;
       };
     main (void)
       {
       FILE *fp;
       struct char_int s;
              :
       fp = fopen("myfile", "w");
       fwrite(&s, sizeof(s), 1, fp);
              :
       }

The alignment for the struct that is written to myfile in the above
example is shown in the following diagram.

[]
Figure 2-7. Comparison of HPUX_WORD and HPUX_NATURAL Byte Alignments In the HPUX_WORD alignment mode, six bytes are written to myfile. The integer field2 begins on the third byte. In the HPUX_NATURAL alignment mode, eight bytes are written to myfile. The integer field2 begins on the fifth byte. Declaring the HP_ALIGN Pragma The HP_ALIGN pragma controls data storage allocation and alignment of structures, unions, and type definitions, using typedefs. It enables you to control the alignment mode when allocating storage space for data. It is especially important when used to control the allocation of binary data that is transmitted among machines having different hardware architectures. The HP_ALIGN pragma takes a parameter indicating which alignment mode to use. Not all modes are available on all HP platforms; the NATURAL alignment mode is the most widely available on HP-UX. This mode is the recommended standard. The syntax for the HP_ALIGN pragma is: #pragma HP_ALIGN align_mode [PUSH] #pragma HP_ALIGN POP where align_mode is one of the following: HPUX_WORD This is the Series 300/400 alignment mode. HPUX_NATURAL_S500 This is the Series 500 alignment mode. HPUX_NATURAL This is the Series 700/800 alignment mode. (The default mode for HP 9000 Series 700/800 and HP 3000 Series 900 systems.) NATURAL This mode provides a consistent alignment scheme across HP architectures. DOMAIN_WORD This is the word alignment mode on HP Apollo architecture. DOMAIN_NATURAL This is the natural alignment mode on HP Apollo architecture. MPE_16 This is the HP 3000 Series 4x/5x/6x/7x (MPE V) alignment mode, and is only available on MPE/iX systems. NOPADDING This causes all structures and union members that are not bit-fields to be packed on a byte boundary. It does not cause compressed packing where there are zero bits of padding. It only insures that there will be no full bytes of padding in the structure or union.
NOTE The above alignment modes are only available on HP-UX systems, with the exception of the MPE_16 alignment mode, which is only available on MPE/iX.
If the optional parameter PUSH is used with an align_mode argument, the current alignment mode is saved (on an alignment mode stack) and the specified align_mode becomes the new alignment mode. The #pragma HP_ALIGN POP restores the alignment mode last pushed on the alignment mode stack. If the alignment mode stack is empty, the compiler makes the default alignment the current alignment. The HP_ALIGN pragma affects struct and union definitions as well as typedef declarations. It causes data objects that are later declared using these types to have the size and alignment as specified by the pragma. The alignment pragma in effect at the time of data type declaration has significance. The alignment pragma in effect at the time of data type declaration has precedence over the alignment pragma in effect when space for a data object of the previously declared type is allocated. Using the HP_ALIGN Pragma. The HP_ALIGN pragma must have a global scope; it must be outside of any function or enclosing structure or union. For example, suppose you have the following sequence of pragmas: #pragma HP_ALIGN HPUX_WORD PUSH struct string_1 { char *c_string; int counter; }; #pragma HP_ALIGN HPUX_NATURAL PUSH struct car { long double car_speed; char *car_type; }; #pragma HP_ALIGN POP struct bus { int bus_number; char bus_color; }; #pragma HP_ALIGN POP Variables declared of type struct string_1, are aligned according to the HPUX_WORD alignment mode. Variables declared of type struct car, are aligned according to the HPUX_NATURAL alignment mode. Variables declared of type struct bus are aligned according to HPUX_WORD. Accessing Non-Natively Aligned Data with Pointers. Be careful when using pointers to access non-natively aligned data types within structures and unions. Alignment information is significant, as pointers may be dereferenced with either 8-bit, 16-bit, or 32-bit machine instructions. Dereferencing a pointer with an incompatible machine instruction usually results in a run-time error. HP C permanently changes the size and alignment information of typedefs defined within the scope of an HP_ALIGN pragma. It makes data objects, such as pointers, declared by using typedefs, compatible with similar objects defined within the scope of the pragma. For example, a pointer to an integer type declared with a typedef that is affected by the HP_ALIGN pragma will be dereferenced safely when it points to an integer object whose alignment is the same as that specified in the pragma. The typedef alignment information is persistent outside the scope of the HP_ALIGN pragma. An object declared with a typedef will have the same storage and alignment as all other objects declared with the same typedef, regardless of the location of other HP_ALIGN pragma statements in the program. There is a slight performance penalty for using non-native data alignments. The compiler generates slower but safe code for dereferencing non-natively aligned data. It generates more efficient code for natively aligned data. The following program generates a run-time error because a pointer that expects word-aligned data is used to access a half-word aligned item: #pragma HP_ALIGN HPUX_WORD struct t1 { char a; int b;} non_native_rec; #pragma HP_ALIGN POP main () { int i; int *p = &non_native_rec.b; i = *p; /* assignment causes run-time bus error */ } The following program works as expected because the pointer has the same alignment as the structure: #pragma HP_ALIGN HPUX_WORD struct t1 { char a; int b;} non_native_rec; typedef int non_native_int; #pragma HP_ALIGN POP main () { int i; non_native_int *p = &non_native_rec.b; i = *p; } An alternative to using the HP_ALIGN pragma and typedefs to control non-natively aligned pointers is to use the +ubytes compiler option of HP C/HP-UX. The +ubytes forces all pointer dereferences to assume that data is aligned on 8-bit, 16-bit, or 32-bit addresses. The value of bytes can be 1 (8-bit), 2 (16-bit), or 4 (32-bit). This option can be used when accessing non-natively aligned data with pointers that would otherwise be natively aligned. This option can be useful with code that generates the compiler warning message: #565 - "address operator applied to non natively aligned member." and aborts with a run-time error. The +ubytes option affects all pointer dereferences within the source file. It can have a noticeable, negative impact on performance.
NOTE The HP C/iX implementation of the +u option omits the bytes parameter. Specifying this option on MPE/iX forces all pointers to be accessed with 16-bit addressing.
Defining Platform Independent Data Structures One way to avoid trouble caused by differences in data alignment is to define structures so they are aligned the same on different systems. To do this, use padding bytes--that is, dummy variables to align fields the same way on different architectures. For example, use: struct { char cl; char dum1; char dum2; char dum3; int i1; }; instead of: struct { char c1; int i1; };


MPE/iX 5.0 Documentation