Re: Alignment in structs
Re: Alignment in structs
- Subject: Re: Alignment in structs
- From: Rush Manbert <email@hidden>
- Date: Mon, 17 Jul 2006 11:29:15 -0700
Laurence Harris wrote:
On Jul 14, 2006, at 9:41 PM, Steve Checkoway wrote:
On Jul 14, 2006, at 6:05 PM, Laurence Harris wrote:
On Jul 14, 2006, at 6:59 PM, Rush Manbert wrote:
Laurence Harris wrote:
What do I need to set in Xcode to get the size of this struct:
typedef struct Blah {
UInt32 a, b, c;
SInt16 d;
} Blah;
to be 14 instead of the 16 I'm getting currently? Thanks,
Try this:
typedef struct Blah {
UInt32 a, b, c;
SInt16 d;
} __attribute__((__packed__)) Blah;
When I try this, the following line:
err = Foo( x, data.a );
generates this warning:
: error: cannot bind packed field 'data.Blah::a' to 'UInt32&'
OSErr Foo ( FSVolumeRefNum inVRefNum, UInt32 &inID );
Just a guess but the packed fields do not necessarily have the
natural alignment that that would be required for that type so gcc
either has to do some unaligned loads or load the surrounding bytes
and do some bit shifts. A reference is just like a pointer (with
fewer capabilities) and wouldn't handle unaligned loads/stores. There
might be a way to get gcc to emit code to check the address and
handle calls to Foo with both aligned and unaligned reference
parameters but I don't know how. I'd avoid packing your struct if at
all possible or doing:
Blah data = { 1, 2, 3, 4 };
UInt32 a = data.a;
err = Foo( x, a );
data.a = a;
Okay, this is weird. I took out the __attribute__((__packed__)) when I
got the error. Then I put it back and was going to use your suggestion,
but I don't get the error now. I wonder if there was some kind of
compiler error the first time.
From what I've read, it appears that gcc would not complain if the
calling argument were a const reference. It seems that read only access
of packed data members is fine, but write access through a reference is
not. If the calling argument is a pointer to UInt32, that will be okay
with the compiler too. I don't really understand why references are
restricted in this way, but I assume there's a good (if obscure) reason.
An alternative way to manage the packing is on a data member basis, i.e.:
typedef struct Blah {
UInt32 a,b,c;
SInt16 d __attribute__((__packed__));
} Blah;
This aligns the 32 bit values on 4 byte boundaries, so each instance of
a Blah will be aligned on a 4 byte boundary. That would get you around
the reference binding problem for the UInt32 members, but moves it to
the SInt16 member. Note also that since each instance of Blah will be 4
byte aligned, there will be 2 dead bytes in memory between myBlah and
myBlah2 if you do this:
Blah myBlah, myBlah2;
which isn't the case when you pack the entire struct.
What is it that you're really trying to achieve? Do you have a billion
instances of Blah, so you need to save those 2 bytes? Are you sending
Blahs over the wire to a remote location using some custom protocol? Or
does it just bug you that the size is padded out?
- Rush
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Xcode-users mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden