HP C Programmer's Guide (92434-90009)

128 Chapter5
Programming for Portability
General Portability Considerations
Series 300/400 and Series 700/800 would look like this:
struct S {
char c1; /* byte 0 */
char pad1,pad2,pad3; /* bytes 1 through 3 */
int i; /* bytes 4 through 7 */
char c2; /* byte 8 */
char pad9,pad10,pad11, /* bytes 9 */
pad12,pad13,pad14, /* through */
pad15; /* 15 */
double d; /* bytes 16 through 23 */
};
Casting Pointer Types
Before understanding how casting pointer types can cause portability problems, you must
understand how Series 700/800 aligns data types. In general, a data type is aligned on a
byte boundary equivalent to its size. For example, the char data type can fall on any byte
boundary, the int data type must fall on a 4-byte boundary, and the double data type
must fall on an 8-byte boundary. A valid location for a data type would then satisfy the
following equation:
location
mod sizeof(
data_type
) == 0
Consider the following program:
#include <string.h>
#include <stdio.h>
main()
{
struct chStruct {
char ch1; /* aligned on
an even boundary */
char chArray[9]; /* aligned on
an odd byte boundary */
} foo;
int *bar; /* must be aligned
on a word boundary */
strcpy(foo.chArray, "1234"); /* place a value
in the ch array */
bar = (int *) foo.chArray; /* type cast */
printf("*bar = %d\n",*bar); /* display the value */
}
Casting a smaller type (such as char) to a larger type (such as int) will not cause a
problem. However, casting a char* to an int* and then dereferencing the int* may cause
an alignment fault. Thus, the above program crashes on the call to printf() when bar is
dereferenced.
Such programming practices are inherently non-portable because there is no standard for
how different architectures reference memory. You should try to avoid such programming
practices.