Byte Order in a Word

The order of bytes within an integral type longer than a byte (short, int, or long) can vary among machines. Code that assumes an internal order is not portable, as shown by this example:

/*

* Nonportable structure to access an

* int in bytes.

*/

struct tag_int_bytes

{

char lobyte;

char hibyte;

};

A more portable way to access the individual bytes in a word is to define two macros that rely on the constant CHAR_BIT, defined in LIMITS.H:

#define LOBYTE(a) (char)((a) & 0xff)

#define HIBYTE(a) (char)((unsigned)(a) >> CHAR_BIT)

The LOBYTE macro is still not completely portable. It assumes that a char is eight bits long, and it uses the constant 0xff to mask the high-order eight bits. Because portable programs cannot rely on a given number of bits in a byte, consider the revision below:

#define LOBYTE(a) (char)((a) & ((unsigned)~0>>CHAR_BIT))

#define HIBYTE(a) (char)((unsigned)(a) >> CHAR_BIT)

The new LOBYTE macro performs a bitwise complement on 0; that is, all zero bits are turned into ones. It then takes that unsigned quantity and shifts it right far enough to create a mask of the correct length for the implementation.

The following code assumes that the order of bytes in a word will be least-significant first:

int c;

.

.

.

fread( &c, sizeof( char ), 1, fp );

The code attempts to read one byte as an int, without converting it from a char. However, the code will fail in any implementation where the low-order byte is not the first byte of an int. The following solution is more portable. In this example, the data is read into an intermediate variable of type char before being assigned to the integer variable.

int c;

char ch;

.

.

.

fread( &ch, sizeof( char ), 1, fp );

c = ch;

The following example shows how to use the C run-time function fgetc to return the value. The fgetc function returns type char, but the value is promoted to type int when it is assigned to a variable of type int.

int c;

.

.

.

c = fgetc( fp );

Microsoft C Specific

Microsoft C normally aligns data types longer than one byte to an even-byte address for improved performance. See the /Zp compiler option in Chapter 13, “CL Command Reference,” of the Environment & Tools manual; see the pack pragma in the C Language Reference or in Help for information about controlling structure packing in Microsoft C.