<<
 
>>
 
 
justin = {main feed , music , code , askjf , pubkey };
 
Today I found this out
January 10, 2010
(after spending much of the day banging my head against the wall)
#include <stdio.h>
struct test1 {  double b; };
struct test2 { int a; test1 b; };
test2 foo;
int main() 
{
  printf("%d\n",(int)&foo.b.b - (int)&foo);
  return 0;
}
What does this print? On Windows, it prints 8. On OS X (or linux), it prints 4. Which means, if you access foo.b.b a lot, it will be slow. UGH. I guess that's why there's -malign-double for gcc. Now if I can just figure out how to enable that for Xcode...



Recordings:

freeform jam with brennewtnoj

7 Comments:

Posted by Scott on Mon 11 Jan 2010 at 06:12 from 86.169.237.x

(1:49:35 PM) Scott: 1014.org/?article=405#c405cake teapots
(1:54:13 PM) Will: the reason that happens is because x86/64 is lame and lets you align things to any boundary
(1:54:49 PM) Will: a lot of CPUs won't let you read a double from an address that isn't a multiple of 8
(1:55:20 PM) Will: it will trigger a bus error
(1:56:20 PM) Will: it's fairly common knowledge not to pack structs in a lame order
(1:56:23 PM) Will: that guy is a noob.

Posted by Justin on Mon 11 Jan 2010 at 07:00 from 74.66.229.x

Whatever. PPC lets you do it as well (with a performance penalty). The reality is that gcc is lame -- doubles are aligned to 8 byte boundaries on the stack, or in the static section. Why shouldn't they be in a struct as well? Any reasonable ABI should have this be.

Posted by Justin on Mon 11 Jan 2010 at 07:08 from 74.66.229.x

Nevermind that (at least on 32-bit OSes), this would produce an unaligned double:

class foo { double a; virtual void blah() { }; };

Posted by Lubo on Wed 20 Jan 2010 at 16:33 from 90.154.197.x

well..gcc (!=lame imho) does have the compiler flags and also things like:

struct foo { int x[2] __attribute__ ((aligned (8))); };

i think that as much as structs look simpler and are in just for the c compat, they can end up more or less as an 'issue trap'. i generally try to avoid them and unions asm-asp.

the class 'treatment' on the other hand will most likely have no performance penalty what so ever.

Posted by Lubo on Wed 20 Jan 2010 at 16:40 from 90.154.197.x

ps: basically the above line solves the alignment of 'b' as:
struct test1 { double b __attribute__ ((aligned (8))); };

and now 'b' is considered independent of the compiler flags (-mno-align-double / -align-double)

Posted by Lubo on Wed 20 Jan 2010 at 17:24 from 90.154.197.x

ps2:
/sorry for multiple posts/

or...alternatively using pragma pack, which should be more portable but apparently not recommended with gcc:

//-----------
#include

#pragma pack(push, 8) //align = 8
#pragma pack(8)

struct test1 { double b; };
struct test2 { int a; test1 b; };
test2 foo;

#pragma pack(pop) //pop back
#pragma pack()

int main()
{
printf("%dn",(int)&foo.b.b - (int)&foo);
return 0;
}
//-----------

Posted by Justin on Wed 20 Jan 2010 at 17:32 from 204.11.104.x

yeah, the __attribute__ use is the only solution that realistically works on OS X. Have to do some #ifdefs etc so that you can make stuff compile on other compilers too. the #pragma packs dont work on OS X. gcc != lame, but whoever decided that structs with doubles should be packed to 4 byte boundaries on these ABIs was not very thoughtful. "Avoiding structs" is not a good idea, IMO, because of course classes are structs, too.

Add comment:

Name:
Human?: (no or yes, patented anti crap stuff here)
Comment:
search : rss : recent comments : Copyright © 2024 Justin Frankel