On Thu, Apr 25, 2002 at 01:56:19PM -0700, Danny Epstein wrote:
> I just did some experiments with an older version of CodeWarrior (68K). I
> found that you could use:
> 
>       #pragma pack(push, 1)
>       typedef struct {...} FooType;
>       #pragma pack(pop)
[...]
> to eliminate padding. This allows sizeof(FooType) to be odd. However, the
> code generated for accessing an unaligned field is the same as for an
> aligned field: a simple move instruction. This will fail with an address
> error on Poser or a real device (but not in the old Mac simulator).

Interesting.  I had not expected that these #pragmas would produce code
that just plain crashes!  What on earth is "pack(push, 1)" for, then? :-)
You said this was a old version; I wonder what current m68k CW does...

> The ADS ARM compiler has an __packed type qualifier that eliminates padding
> and forces the compiler to generate code to do unaligned accesses. Several
> instructions are needed in place of a single MOV instruction.
> 
> I don't know what GCC supports, either in 68K or ARM.

The GCC documentation (which is available on the Web) says

     The `packed' attribute specifies that a variable or structure field
     should have the smallest possible alignment--one byte for a
     variable, and one bit for a field, unless you specify a larger
     value with the `aligned' attribute.

Hmmm... I thought the documentation was more explicit than this.

But, for example, if you use __attribute__((packed)) on a UInt16 with
m68k GCC, the variable will have alignment 1, which is looser than the
alignment requirements of the m68k's 16 bit instructions, so GCC will
generate two 8 bit move instructions to do the work.  I.e., it generates
the same sort of code as the ADS ARM compiler you mentioned.  I thought
this was more explicit in the documentation, but I guess they didn't
feel the need to write "the resulting code *does* actually work" :-).

And previously Joe Onorato <[EMAIL PROTECTED]> wrote:
> It doesn't matter so much on 68k, but on some other platforms (ARM)
> unaligned access is significantly slower than aligned access.

Actually, on m68k, at least on Palm OS (because the OS doesn't supply
a handler for the relevant processor exception), unaligned access is
infinitely slower than aligned access.  Can you say "address error"?! :-)

Or, as we've seen, if the compiler can tell that the access you're
asking for is potentially unaligned (e.g., you're using GCC and the
access in question is to some larger-than-byte variable that you've
marked with __attribute__((packed))), it can generate larger slower
code that accesses the variable a byte at a time or so and thus avoids
actually doing an unaligned access.

This wastes both time *and* code space, which on m68k is still fairly
precious :-).

> So unless you have a particular reason to pack the struct, you'd be
> better off not packing it and using sizeof().

Agreed.  Even where there is a particular reason, I wouldn't use packing
attributes on a typedef that was used thoughout a program.  Instead I'd
just use them on a shadow struct that's only in scope in the function
where it's needed, or just plain do it manually.

In summary, with GCC if Jay put __attribute__((packed)) on at least
four of the UInt16s in his struct, then sizeof(InfoRecordStruct) really
would be 21 and his code would work, albeit a little more slowly and a
little bigger.

But that would be a really silly thing to do.  The sensible thing to do
would be to rearrange the struct so that the fields with tighter
alignment requirements come first.  Or to just not worry about it:
accept the padding, and never count the size yourself, instead using
sizeof and friends.

    John

-- 
For information on using the Palm Developer Forums, or to unsubscribe, please see 
http://www.palmos.com/dev/support/forums/

Reply via email to