2010-01-23 19 views
3

Pour utiliser OSAtomicDecrement (opération atomique spécifique à mac), je dois fournir un SInt32 aligné sur 4 octets.Comment s'assurer qu'un membre est aligné sur 4 octets?

Ce type de cuisson fonctionne-t-il? Existe-t-il une autre façon de gérer les problèmes d'alignement?

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

    SInt32 *member_; 

    struct { 
    SInt32 a; 
    SInt32 b; 
    } storage_; 
}; 

Répondre

5

Si vous utilisez un Mac, cela signifie GCC. GCC peut aligner automatiquement les variables pour vous:

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

S'il vous plaît noter que ce ne sont pas des compilateurs à travers portables, comme cela est spécifique du CCG.

+2

Quel est l'avantage de cette solution car elle est moins portable (et un espace supplémentaire de 4 octets utilisé est ok)? – gaspard

+0

Je ne veux pas vraiment ajouter un autre '#ifdef __gcc__' ... – gaspard

+0

-1: ceci s'assure que le stockage pour le pointeur est aligné. Oui, puisqu'il est aligné storage_ serait également aligné mais c'est indirect et déroutant. Si vous voulez recommander l'alignement, ajustez directement la variable (supprimez la structure et créez juste un membre '__attribute __ ((__ aligned (4))) SInt32 a_;' –

0

Je sais rien limites sur la programmation Mac mais que j'ai utilisé des mini-ordinateurs pour travailler, les pointeurs sont toujours alignés sur 4 octets (mot). IIRC, les structures étaient aussi. La mémoire allouée était toujours.

4

Je suppose que tout SInt32 est déjà aligné, même sur un mac.

Pour clarifier:

struct Foo { 
    SInt32 member; 
}; 

membre est toujours correctement aligné, à moins que vous emballez la structure et mettre membre après char.

+0

Ce sera le cas sur PowerPC, mais PAS sur x86. PPC est grand endian - les mots doivent être alignés, mais sur le petit boutiste, il n'y a aucune garantie de cela. – LiraNuna

+2

Aucun compilateur ne génèrerait de code exprès utilisant des accès mal alignés sur un x86. Cela causerait un coup sévère de performance. –

+0

@LiraNuna ce n'est pas vrai. Microsoft Visual C++ et GCC garantissent l'alignement d'int à la limite de 4 octets sur x86. Il est documenté sur MSDN, dans le cas de Visual C++. – mloskot

-1

Si vous voulez forcer un bon alignement dans une structure, vous pouvez utiliser des champs de bits.

struct 
{ 
    Foo _hisFoo; 
    unsigned int dummyAlignment : 0; 
    Foo _myFoo; 
} 
+0

Un champ de bits de longueur nulle remplit la limite d'alignement suivante de son type déclaré de base. Cela entraîne le début du membre suivant sur une limite d'octet (pour les champs de bits char), limite de 2 octets (pour court), limite de 4 octets (pour int ou long) ou limite de 8 octets (pour long long). Le remplissage ne se produit pas si la disposition de la mémoire du membre précédent s'est terminée sur la limite appropriée. – EvilTeach

1

int s sont 4 octets alignés par défaut avec l'un des compilateurs OS X. Tout ce que vous devez faire n'est pas intentionnellement rompre cet alignement (par exemple en faisant des moulages de pointeurs inappropriés, en marquant votre structure comme packed, etc.).

0

Si votre compilateur prend en charge TR1 (ou C++ 0x), vous pouvez utiliser le modèle std::aligned_storage.

Pour allouer de l'espace pour un objet de taille S et d'alignement A, vous pouvez affecter un objet de type std::aligned_storage<S, A>::storage.

(L'espace de noms peut varier entre compilateurs. Je pense que TR1 ne précise pas quel espace les extensions doivent être placés dans. Sur MSVC, l'espace de noms std::tr1 est utilisé)

En dehors de cela, les entiers 32 bits sont déjà 4 octets alignés par le compilateur (au moins sur les plates-formes où l'alignement naturel des ints 32 bits est 4 octets)