From: richk@grebyn.com (Richard Krehbiel)
Subject: Re: sizeof()
Organization: Grebyn Timesharing
Date: Thu, 10 Sep 1992 00:19:22 GMT

In article <Sep.9.14.38.29.1992.10548@turbo.bio.net> will@turbo.bio.net (Will Nelson) writes:
>I've run into an incompatibility between Microsoft C 7.0
>and the unbundled ANSI C compiler (1.1) of SUN Microsystems.

The ANSI standard endorses such incompatibilities.  Your struct member
operator_token is the major culprit here; it causes the struct to be
interpreted differently on the two machines.

>struct Location {
>  char base_position[7];
>  int  operator_token;
>};

In *this particular case*, here's the difference:

                             PC        Sparc
sizeof(base_position)        7           7   (guaranteed by ANSI)
offsetof(base_position)      0           0   (guaranteed by ANSI)
sizeof(operator_token)       2           4   (implementation-defined)
offsetof(operator_token)     8           8   (implementation-defined)

To a portable-C purist, there's no solution to this problem.  You
cannot write data to external storage which is guaranteed to be
readable by any other arbitrary machine, because C does not define
even such fundamental things as the number of bits in a byte; it could
be 8, or 9, or 10, or more.

For practical purposes, you can bet on a number of things that ANSI
doesn't guarantee.  And I emphasise that this is betting; there's no
telling when a machine will come along on which your assumptions are
wrong.

One pretty safe bet is that the character set is ASCII.  This is the
most popular standard by a wide margin.  I'll bet that the readership
of this newsgroup could produce a list of all machines which don't use
ASCII, and you can decide if you'll want to omit those.  All new
machines are capable of dealing with ASCII, even those that use a
newer standard such as Unicode, and in such cases, a Unicode<->ASCII
translator program is trivial.

So you can write out all your data as printable text in the character
set that your C compiler uses, and be pretty sure that you'll read in
the same thing on any other machine.  This is (I believe) as close to
a universal solution as you can come.

(Now, here's where I probably get flamed...)

There are a few other "pretty safe" bets, on things like the number of
bits in a char (nearly always 8), the representation of negative
numbers (2's complement), number of chars in a short (2) and long (4).

Though alignment needs of different computers are typically different,
you can stack the deck in your favor by manually inserting struct
padding to the most likely worst-case alignment needs: make the offset
of each member an exact multiple of it's size, by adding the padding
chars needed, and add similar padding at the end of the struct so that
it's length is an exact multiple of the worst-case alignment of it's
members.

But past those, you're out of bets.  The things that are typically
different are sizeof(int) (as you've discovered), byte ordering of
integers larger than char, and the bit patterns used for float and
double.

(OK.  I'm in enough trouble...)
-- 
Richard Krehbiel                                 richk@grebyn.com
OS/2 2.0 will do for me until AmigaDOS for the 386 comes along...