4

In order to use OSAtomicDecrement (mac-specific atomic operation), I need to provide a 4-byte aligned SInt32.

Does this kind of cooking work ? Is there another way to deal with alignment issues ?

struct SomeClass {
  SomeClass() {
    member_  = &storage_ + ((4 - (&storage_ % 4)) % 4);
    *member_ = 0;
  }

  SInt32 *member_;

  struct {
    SInt32 a;
    SInt32 b;
  } storage_;
};
Anna B
  • 5,997
  • 5
  • 40
  • 52

6 Answers6

5

If you're on a Mac, that means GCC. GCC can auto align variables for you:

  __attribute__((__aligned__(4))) int32_t member_;

Please note that this is not portable across compilers, as this is GCC specific.

LiraNuna
  • 64,916
  • 15
  • 117
  • 140
  • 2
    What is the benefit of this solution since it's less portable (and an extra 4 byte of space used is ok) ? – Anna B Jan 23 '10 at 20:25
  • -1: this makes sure that the storage for the pointer is aligned. Yes, since it's aligned storage_ would also be aligned but that is indirect and confusing. If you want to recommend specifying alignment, just directly align the variable (drop the struct and just create a member `__attribute__((__aligned(4))) SInt32 a_;` – R Samuel Klatchko Jan 23 '10 at 20:38
  • 1
    There is NO "extra 4 bytes used", GCC simply relocates the class to fit your demands. There is also NO WAY of doing so reliably across compilers, MSVC has such an option (__declspec align?). You have special needs that only the linker can accommodate and you think you can get away without compiler-specific options? The pointer was a left-over from the pasted code, it should not be there (edited out). – LiraNuna Jan 23 '10 at 20:42
  • @LiraNuna the 4 extra bytes exist in my example, not in yours. Sorry for the confusion. You might be right, I might not be able to avoid compiler dependencies... – Anna B Jan 23 '10 at 20:56
  • Mac doesn't necessarily mean GCC. One could use clang/llvm, ICC supports OS X, as do a few other compilers. – Stephen Canon Jan 23 '10 at 21:00
  • @Gaspard: You don't need any compiler dependant code. The members are already aligned. – Richard Pennington Jan 23 '10 at 21:00
  • @Richard: Nothing in the C++ specification says that the members are aligned. They are as such because of **compiler optimization** for faster memory access. This does not, in any way **guarantee** of that. Another architecture/compiler might find it better to optimize it otherwise. – LiraNuna Jan 23 '10 at 21:27
  • He's not talking about a standard. He's talking about a specific application and alignment on the mac. I happen to know how gcc and clang deal with alignment for the x86 under OSX, so I thought giving him the right answer was OK. – Richard Pennington Jan 23 '10 at 21:40
  • Removing my down vote as you fixed the pointer issue. That said, why does your example still include the storage_ member? – R Samuel Klatchko Jan 23 '10 at 21:45
  • @LiraNuna: You're correct that it's not guaranteed by the C++ spec, but the C++ spec is not the only relevant document. The OS X abi rules are quite clear that `int`s are 4 byte aligned by default. – Stephen Canon Jan 23 '10 at 21:50
  • @LiraNuna Can you remove the storage thing and use "int32_t" instead (that's the type used in OSAtomic.h). – Anna B Jan 23 '10 at 21:53
  • @Richard I need to be absolutely sure that my code does not produce hazardous results now or in the future and explicitly requiring alignment seems like a good idea. – Anna B Jan 23 '10 at 21:54
  • @Gaspard: That's OK. I've already used up all of my 200 points today, it seems. ;-) – Richard Pennington Jan 23 '10 at 21:56
4

I would guess that any SInt32 is already aligned, even on a mac.

To clarify:

struct Foo {
    SInt32 member;
};

member is always aligned properly, unless you pack the structure and put member after a char.

Richard Pennington
  • 19,673
  • 4
  • 43
  • 72
  • This will be the case on PowerPC, but NOT on x86. PPC is big endian - words must be aligned, but on little endian, there is no guarantee of that. – LiraNuna Jan 23 '10 at 20:14
  • 2
    No compiler would generate code on purpose that used misaligned accesses on an x86. It would cause a severe performance hit. – Richard Pennington Jan 23 '10 at 20:17
  • @LiraNuna it is not true. Microsoft Visual C++ and GCC guarantee alignment of int to 4-byte boundary on x86. It is documented on MSDN, in case of Visual C++. – mloskot Jan 23 '10 at 20:19
  • Absolutely correct. All of the 4-byte basic types are 4-byte aligned by default on OS X. – Stephen Canon Jan 23 '10 at 21:52
1

ints are 4 byte aligned by default with any of the OS X compilers. All you need to do is not intentionally break that alignment (e.g. by doing improper pointer casts, marking your structure as packed, etc).

Stephen Canon
  • 103,815
  • 19
  • 183
  • 269
0

I know nothing about Mac programming but on minicomputers that I used to work on, pointers were always aligned on 4-byte (word) boundaries. IIRC, structs were too. Allocated memory always was.

Mick
  • 4,987
  • 1
  • 19
  • 23
0

If your compiler supports TR1 (or C++0x), you can use the std::aligned_storage template.

To allocate space for an object with size S and alignment A, you can allocate an object of type std::aligned_storage<S, A>::storage.

(The namespace may vary between compilers. I think TR1 doesn't specify which namespace the extensions must be placed in. On MSVC, the namespace std::tr1 is used)

Apart from this, 32-bit integers are already 4-byte aligned by the compiler (at least on the platforms where the natural alignment of 32-bit ints is 4 bytes)

jalf
  • 243,077
  • 51
  • 345
  • 550
-1

If you want to force a nice alignment in a structure, you can use bit fields.

struct 
{
   Foo _hisFoo;
   unsigned int dummyAlignment : 0;
   Foo _myFoo;
}
EvilTeach
  • 28,120
  • 21
  • 85
  • 141
  • A zero-length bit field pads to the next alignment boundary of its base declared type. This causes the next member to begin on a byte boundary (for char bit fields), 2-byte boundary (for short), 4-byte boundary (for int or long), or 8-byte boundary (for long long). Padding does not occur if the previous member's memory layout ended on the appropriate boundary. – EvilTeach Jan 23 '10 at 23:17