[comp.lang.c] Byte vs. Word Alignment

jrb@petro.UUCP (Jon Boede) (04/15/87)

This is probably the most trivial of questions, but I've always wondered if
wordwise alignment affected efficiency on the 68000.

For example, assuming that a structure like:

	struct {
		int an_int;
		char a_char;
	} a_struct;

starts on a word boundry, would a structure placing the /char/ first and the
/int/ therefore a 1/4 word off be less, can we say, "efficient" in terms of
the manipulation needed to get to /an_int/??  Or doesn't the C compiler always
start structures on words boundries, making alignment consideration by the
programmer meaningless?

	struct {
		char a_char;
		int an_int;
	} a_struct;	/* is this less "efficient"? */

Also, whilst I'm on the subject, how much extra effort is required of the
68000 to get to specific bits than to, say, an int?  I often use structures
of bit flags to save space in files.  I can easily compute the space savings,
but an accurate guess as to the time savings is a little more elusive.

Thanks!
-- 
Jon Boede				...!{ihnp4,akgua,gatech}!petro!jrb
512/599-1847				2555 N.E. Loop 410, #1403, 78217
	"People who are incapable of making decisions are
	 the ones who hit those barrels at freeway exits."

dlnash@ut-ngp.UUCP (Donald L. Nash) (04/16/87)

In article <244@petro.UUCP>, jrb@petro.UUCP (Jon Boede) writes:
> This is probably the most trivial of questions, but I've always wondered if
> wordwise alignment affected efficiency on the 68000.
> 
> For example, assuming that a structure like:
> 
> 	struct {
> 		int an_int;
> 		char a_char;
> 	} a_struct;
> 
> starts on a word boundry, would a structure placing the /char/ first and the
> /int/ therefore a 1/4 word off be less, can we say, "efficient" in terms of
> the manipulation needed to get to /an_int/??  Or doesn't the C compiler always
> start structures on words boundries, making alignment consideration by the
> programmer meaningless?
> 
> 	struct {
> 		char a_char;
> 		int an_int;
> 	} a_struct;	/* is this less "efficient"? */

    C compilers reserve the right to pad a structure to make it fit alignment
restrictions.  There might be some unused space between a_char and an_int
to make an_int line up on a word boundary.  I know that 4.3 BSD pcc on a VAX
does this, because I have tested it on similar constructs, ditto 4.2 BSD pcc.
If you are using a 680x0 C compiler derived from either of these (like on 4.2
BSD on a Sun), it probably pads as well.

> Also, whilst I'm on the subject, how much extra effort is required of the
> 68000 to get to specific bits than to, say, an int?  I often use structures
> of bit flags to save space in files.  I can easily compute the space savings,
> but an accurate guess as to the time savings is a little more elusive.

    The 68020 has bit field instructions for dealing with this sort of thing.
How efficient your code is when using bit fields in C depends on whether your
compiler is smart enough to use these instructions.  I don't have a 68000
manual, only a 68020 manual, so I can't tell you for certain if the 68000 has
these instructions, although I assume it does.

				Don Nash

UUCP:    ...!{ihnp4, allegra, seismo!ut-sally}!ut-ngp!dlnash
ARPA:    dlnash@ngp.UTEXAS.EDU
BITNET:	 CCEU001@UTADNX, DLNASH@UTADNX
TEXNET:  UTADNX::CCEU001, UTADNX::DLNASH

UUU       UUU
 U         U                The University of Texas at Austin
 U     TTTTUTTTTTTTTT              Computation Center
 U     T   U TT     T
  U       U  TT            "The world is basically non-linear."
   UUUUUUU   TT
             TT 
            TTTT

wagner@iaoobelix.UUCP (04/18/87)

Byte vs. word alignment is a problem I have encountered recently when I
tried to setup a simple server/client connection using sockets. The problem
was that you get very strange results on a VAX/uVAX/Sun if you print out
sizeof(struct foo) where struct foo is:

	struct foo {
		char frob_1;
		int frob_2;
	};

I intended to send something like the above structure as a packet over the
net. You know what happened? The VAX/uVAX produces *8* as sizeof struct foo,
whereas the Sun program yields *6*. The client program, run on the VAX sent
a packet of size 8, and the daemon on the Sun thought the packet size was 6.
Yet, things get even worse if you use something like

	struct packet {
		char packet_type;
		struct foo packet_data;
	}

Aarrgh! You get *8* on a Sun and *12* on a VAX/uVAX. The whole structure is
not being packed together into eight bytes (with the two chars in the first
word) but each char is placed in a 4-byte (four-byte!) word! BTW, the same
holds for shorts (2 bytes).

Maybe there should be a compiler switch -dont_align forcing the compiler to
take things literally, i.e. to leave these structs unchanged even if their
size is an odd number of bytes. The structures themselves could be word
aligned *in memory*, however, but the internal structure would be as the
programmer defined it.

Note: If you think of something like `unsigned frob: 8;' to get the desired
result... No chance! You will get exactly the same sizes for the structures on
both Sun and VAX/uVAX.

Juergen Wagner,		     (USENET) ...seismo!unido!iaoobel!wagner
("Gandalf")			 Fraunhofer Institute IAO, Stuttgart

edw@ius2.cs.cmu.edu (Eddie Wyatt) (04/21/87)

In article <6700007@iaoobelix.UUCP>, wagner@iaoobelix.UUCP writes:
> 
> 	struct foo {
> 		char frob_1;
> 		int frob_2;
> 	};
> 
> I intended to send something like the above structure as a packet over the
> net. You know what happened? The VAX/uVAX produces *8* as sizeof struct foo,
> whereas the Sun program yields *6*. The client program, run on the VAX sent
> a packet of size 8, and the daemon on the Sun thought the packet size was 6.

  Comment aside from byte alignment. If the Vax has to interpret that
structure (ie needs to use frob_2) , you may find it a problem since byte
ordering of integers differ on Vaxen and Suns.  I suggest you look at the
eXternal Data Representation (XDR) section of the sun networking manual.
You may find it a problem to use those since as far as I know, neither Berkley
nor Sys V support these networking primatives sign :-(. But suppositely
Mach will take care of this by supporting its own version of XDR :-).
Well I shall find out.

-- 
					Eddie Wyatt

They say there are strangers, who threaten us
In our immigrants and infidels
They say there is strangeness, too dangerous
In our theatres and bookstore shelves
Those who know what's best for us-
Must rise and save us from ourselves

Quick to judge ... Quick to anger ... Slow to understand...
Ignorance and prejudice and fear [all] Walk hand in hand.
					- RUSH 

wesommer@athena.mit.edu (William Sommerfeld) (04/21/87)

In article <6700007@iaoobelix.UUCP> wagner@iaoobelix.UUCP writes:
>Byte vs. word alignment is a problem I have encountered recently when I
>tried to setup a simple server/client connection using sockets. The problem
>was that you get very strange results on a VAX/uVAX/Sun if you print out
>sizeof(struct foo) where struct foo is:
		[ a structure with an char and an int ]

You're *still* in trouble even if the two compilers used the same
alignment rules.  Ever hear of byte order?

The "right" way to do something like this is to use an architecture
independant network representation, like SUN's XDR  (eXternal Data
Representation), or Universal Stream Protocol (developed by Clark et.
al. at MIT).  To assume that you can declare a structure and just copy
its bit image onto the net and onto another machine is incorrect.

>Maybe there should be a compiler switch -dont_align forcing the compiler to
>take things literally, i.e. to leave these structs unchanged even if their
>size is an odd number of bytes. The structures themselves could be word
>aligned *in memory*, however, but the internal structure would be as the
>programmer defined it.

That's not going to work on some architectures.  For example, on an
IBM RT PC, you *can't* do an unaligned longword load in any kind of
efficient manner (the hardware *silently* rounds your pointers down).
On other architectures, you get a hardware trap if you try and do
this.  All the world is not a VAX.. or even a 32 bit register machine
with 8 bit byte addressable memory.

					Bill Sommerfeld
					MIT Project Athena
				  ARPA: wesommer@athena.mit.edu
				  UUCP: ...!mit-eddie!wesommer

"C is PL/I that's been left on the stove too long (most of it
has boiled awa@s@s

prl@ethz.UUCP (Peter Lamb) (04/21/87)

In article <6700007@iaoobelix.UUCP> wagner@iaoobelix.UUCP writes:
>
>	struct foo {
>		char frob_1;
>		int frob_2;
>	};
>
>I intended to send something like the above structure as a packet over the
>net. You know what happened? The VAX/uVAX produces *8* as sizeof struct foo,
>whereas the Sun program yields *6*.

I am always surprised when people write code that sends raw binary
data, especially structures, over networks. I can imagine that there
will be lots of horrible hacking to make this all work between Sun and
Vax, then along comes another machine with yet other sizes/alignment
requirements and the whole thing gets worse and worse....  (the size of
the above array on a PDP11, for example, is *4*).

Wait until you want to send *floats* :-( .

The safest way to send data (especially floats) is as an array of bytes
with an agreed most-to-least significant byte ordering. For floating
point break out the exponent and fraction and encode them separately:
make sure that the exponent is always to the same base (IBM 360 &
lookalikes have base 16 not base 2; ie fpnum = fraction * 16^exponent).

If portability rather than efficiency is the main consideration, use a
printable encoding using sprintf/ato[ilf].

Writing code which handles binary data portably is *hard*.

prl@ethz.UUCP (Peter Lamb) (04/21/87)

Our new news version stomped on my signature for the last article
because it was longer than 4 lines (sigh). Here it is anyway....

Peter Lamb				uucp:  seismo!mcvax!ethz!prl
Tel: (01) 256 5241 (Switzerland)	eunet: prl@ethz.uucp
     +411 256 5241 (International)	earn:  PRL@CZHETH5A

Institut fuer Integrierte Systeme	Institute for Integrated Systems
ETH-Zentrum				ETH-Zentrum
8092 Zuerich				8092 Zurich

V125KJG8%UBVMS.BITNET@wiscvm.wisc.EDU (04/21/87)

In article <5025@ut-ngp.UUCP>, dlnash@ut.ngp.uucp (Donald L. Nash) writes:
>In article <244@petro.UUCP>, jrb@petro.UUCP (Jon Boede) writes:
>> Also, whilst I'm on the subject, how much extra effort is required of the
>> 68000 to get to specific bits than to, say, an int?  I often use structures
>> of bit flags to save space in files.  I can easily compute the space savings,
>> but an accurate guess as to the time savings is a little more elusive.
>
>    The 68020 has bit field instructions for dealing with this sort of thing.
>How efficient your code is when using bit fields in C depends on whether your
>compiler is smart enough to use these instructions.  I don't have a 68000
>manual, only a 68020 manual, so I can't tell you for certain if the 68000 has
>these instructions, although I assume it does.

Stand by, Don, I'll have to fetch my 68000 User's Manual...

The 68000 instructions BTST, BSET, BCLR, and BCHG instructions (M68000
Programmer's Reference Manual (1984), p. 30, 73-82) do exist, HOWEVER the BF
series instructions (MC68020 User's Manual (1985), p. B31-B45) do not.
Unfortunately, this would mean multiple calls to the B-series 68000 instructions
to do the same.  SLOWSLOWSLOWSLOW...

Let's hope that the good 68020 compilers can use these instructions.  Folks?
Can you fill us in?

Have fun and see yuh (Happy Easter!)...
  --Curtis R. Anderson
    (Just a student at...)
    State University of New York at Buffalo (so I have the standard disclaimer
    here!)

(V125KJG8@UBVMS.BITNET, C125KJG8@UBVM.BITNET,
V125KJG8%UBVMS.BITNET@WISCVM.WISC.EDU, etc...)

wagner@iaoobelix.uucp (04/21/87)

Byte vs. word alignment is a problem I have encountered recently when I
tried to setup a simple server/client connection using sockets. The problem
was that you get very strange results on a VAX/uVAX/Sun if you print out
sizeof(struct foo) where struct foo is:

    struct foo {
        char frob_1;
        int frob_2;
    };

I intended to send something like the above structure as a packet over the
net. You know what happened? The VAX/uVAX produces *8* as sizeof struct foo,
whereas the Sun program yields *6*. The client program, run on the VAX sent
a packet of size 8, and the daemon on the Sun thought the packet size was 6.
Yet, things get even worse if you use something like

    struct packet {
        char packet_type;
        struct foo packet_data;
    }

Aarrgh! You get *8* on a Sun and *12* on a VAX/uVAX. The whole structure is
not being packed together into eight bytes (with the two chars in the first
word) but each char is placed in a 4-byte (four-byte!) word! BTW, the same
holds for shorts (2 bytes).

Maybe there should be a compiler switch -dont_align forcing the compiler to
take things literally, i.e. to leave these structs unchanged even if their
size is an odd number of bytes. The structures themselves could be word
aligned *in memory*, however, but the internal structure would be as the
programmer defined it.

Note: If you think of something like `unsigned frob: 8;' to get the desired
result... No chance! You will get exactly the same sizes for the structures on
both Sun and VAX/uVAX.

Juergen Wagner,             (USENET) ...seismo!unido!iaoobel!wagner
("Gandalf")             Fraunhofer Institute IAO, Stuttgart

guy%gorodish@Sun.COM (04/21/87)

> Byte vs. word alignment is a problem I have encountered recently when I
> tried to setup a simple server/client connection using sockets.

Yup - and I know of another machine whose padding rules are different
from both VAX and Sun (CCI 6/32 - last time I looked, which
admittedly was a while ago, it aligned structures at least on 4-byte
boundaries, as opposed the VAX PCC which aligns them to the boundary
of the most strictly aligned member and the Sun PCC which aligns them
to the more restrictive of "most strictly aligned member" and "2
bytes").

The moral of the story is "don't send raw structures over the wire if
you can possibly avoid it" (note that you couldn't have sent *raw*
structures over the wire anyway unless you had the receiving program
fix the byte order, if necessary).

edw@ius2.cs.cmu.EDU (04/21/87)

In article <6700007@iaoobelix.UUCP>, wagner@iaoobelix.UUCP writes:
>
>     struct foo {
>         char frob_1;
>         int frob_2;
>     };
>
> I intended to send something like the above structure as a packet over the
> net. You know what happened? The VAX/uVAX produces *8* as sizeof struct foo,
> whereas the Sun program yields *6*. The client program, run on the VAX sent
> a packet of size 8, and the daemon on the Sun thought the packet size was 6.

  Comment aside from byte alignment. If the Vax has to interpret that
structure (ie needs to use frob_2) , you may find it a problem since byte
ordering of integers differ on Vaxen and Suns.  I suggest you look at the
eXternal Data Representation (XDR) section of the sun networking manual.
You may find it a problem to use those since as far as I know, neither Berkley
nor Sys V support these networking primatives sign :-(. But suppositely
Mach will take care of this by supporting its own version of XDR :-).
Well I shall find out.

--
                    Eddie Wyatt

They say there are strangers, who threaten us
In our immigrants and infidels
They say there is strangeness, too dangerous
In our theatres and bookstore shelves
Those who know what's best for us-
Must rise and save us from ourselves

Quick to judge ... Quick to anger ... Slow to understand...
Ignorance and prejudice and fear [all] Walk hand in hand.
                    - RUSH

wesommer@athena.mit.EDU (04/21/87)

In article <6700007@iaoobelix.UUCP> wagner@iaoobelix.UUCP writes:
>Byte vs. word alignment is a problem I have encountered recently when I
>tried to setup a simple server/client connection using sockets. The problem
>was that you get very strange results on a VAX/uVAX/Sun if you print out
>sizeof(struct foo) where struct foo is:
        [ a structure with an char and an int ]

You're *still* in trouble even if the two compilers used the same
alignment rules.  Ever hear of byte order?

The "right" way to do something like this is to use an architecture
independant network representation, like SUN's XDR  (eXternal Data
Representation), or Universal Stream Protocol (developed by Clark et.
al. at MIT).  To assume that you can declare a structure and just copy
its bit image onto the net and onto another machine is incorrect.

>Maybe there should be a compiler switch -dont_align forcing the compiler to
>take things literally, i.e. to leave these structs unchanged even if their
>size is an odd number of bytes. The structures themselves could be word
>aligned *in memory*, however, but the internal structure would be as the
>programmer defined it.

That's not going to work on some architectures.  For example, on an
IBM RT PC, you *can't* do an unaligned longword load in any kind of
efficient manner (the hardware *silently* rounds your pointers down).
On other architectures, you get a hardware trap if you try and do
this.  All the world is not a VAX.. or even a 32 bit register machine
with 8 bit byte addressable memory.

                    Bill Sommerfeld
                    MIT Project Athena
                  ARPA: wesommer@athena.mit.edu
                  UUCP: ...!mit-eddie!wesommer

"C is PL/I that's been left on the stove too long (most of it
has boiled away)"

marcus@illusion.UUCP (04/22/87)

In article <244@petro.UUCP> jrb@petro.UUCP (Jon Boede) writes:
>For example, assuming that a structure like:
>
>	struct {
>		int an_int;
>		char a_char;
>	} a_struct;
>
>starts on a word boundry, would a structure placing the /char/ first and the
>/int/ therefore a 1/4 word off be less, can we say, "efficient" in terms of
>the manipulation needed to get to /an_int/??  Or doesn't the C compiler always
>start structures on words boundries, making alignment consideration by the
>programmer meaningless?
>
>	struct {
>		char a_char;
>		int an_int;
>	} a_struct;	/* is this less "efficient"? */

Most compilers would probably pad between a_char and an_int in the second
example so that an_int would be at a word boundary.  It is worth noting that
even in the first example, most compilers will pad 3 bytes to the end of
the structure so that in either case the structure will have a size of 8
bytes (68000 => 32 bit ints).  This is done so that if you had an array
of a_structs, each one would begin at an aligned address.  This seems odd
at first, but after sufficient consideration starts to make sense.

As far as efficiency of referencing an_int is concerned, the first case is
probably going to be more efficient, but not because of alignment.  The
first element in a structure can usually be accessed easier than any other
elements because its offset in the structure is 0 and the compiler can
probably generate simplified addressing modes to get to it.

Marcus Hall
..!{ihnp4,mcdchg}!illusion!marcus
	The illusion is complete, it is reality, the reality
	is an illusion, and the ambiguity is the only truth.

wagner@iaoobelix.UUCP (04/23/87)

Puh! Perhaps, I shouldn't have posted this little article... My mailbox
contained at least two or three responses to my posting every morning.

I should say that I am quite familiar with all the data transmission stuff and
related problems. The article I have posted to the net was just thought as a
useful hint for other people in net.land encountering problems like those
discussed.

Well, XDR is one of the little nice things people (like me) *HAVE* to use if
they don't want to run into a lot of trouble with incompatible data structure
organizations and byte orders. Yet, for quite a number of machines there is
*NO* XDR package what can make data portability a real headache. And, of
course, I didn't get trouble with byte ordering at any time (using `htonl' and
friends).

The article I posted was just to point out the very general alignment problems
one encounters in a heterogenous network without a standardized, machine-
independent external representation formalism.

Yours networkingly,
Juergen Wagner,		     (USENET) ...seismo!unido!iaoobel!wagner
("Gandalf")			 Fraunhofer Institute IAO, Stuttgart