2010-02-16 9 views
2

Est-ce une bonne pratique de regrouper toutes les variables de même type lors de la déclaration en local dans une fonction? Si oui, pourquoi? Résout-il les problèmes d'alignement de la mémoire?Question relative à l'alignement

Répondre

6

Je pense que cela importait avec le compilateur VAX C que j'avais utilisé il y a 20 ans, mais pas avec un compilateur moderne. C'est pas sûr de supposer que les variables locales seront dans un ordre particulier, certainement pas sûr de supposer qu'ils seront dans l'ordre que vous les avez déclarés. J'ai définitivement vu le compilateur MSVC les réorganiser.

Variables de regroupement du même type aide quand elles sont des champs d'une structure, car l'ordre des zones d'une structure est garanti pour correspondre à l'ordre de déclaration.

+0

@Blindy: vous l'avez en arrière de ce que dit la réponse de John. – unwind

+0

@Blindy: John a dit le contraire, que la commande d'une structure est garantie. –

+0

Désolé ma mauvaise, je l'ai mal lu. – Blindy

3

Cela dépend du compilateur; c'est-à-dire que le compilateur disposera la mémoire comme bon lui semble. Donc, en plus d'être un bon style, cela n'a aucun effet (au moins dans les compilateurs modernes que j'ai utilisés).

1

Cela ne résoudra pas les problèmes d'alignement, car il ne devrait pas y avoir de problèmes d'alignement - le compilateur affichera vos variables locales correctement alignées, donc il ne devrait pas y avoir de problèmes d'alignement.

La seule question que le regroupement comme alignés types pourrait ont est de réduire l'utilisation de la pile, mais les compilateurs sont libres de réorganiser la mise en page des variables sur la pile de toute façon (ou même réutiliser des emplacements pour les différentes variables locales à différents fois, ou pour garder les locaux dans les registres et ne jamais les avoir sur la pile), vous n'achetez généralement rien pour une compilation optimisée. Si vous voulez utiliser des objets de type "punition" sur la pile, vous devrez utiliser les mêmes méthodes de sécurité d'alignement que celles utilisées pour les données de la pile - peut-être plus, puisque la mémoire allouée par malloc() ou new est garanti pour être aligné de façon appropriée pour tout type - cette garantie n'est pas faite pour le stockage alloué aux variables automatiques. Le type de punition est lorsque vous contournez le système de types. par exemple en accédant à la octets dans un tableau char comme int par coulée d'un char* à un int*:

int x; 
char data[4]; 

fill_data(data, sizeof(data)); 

int x = *(int*) data; 

Étant donné que l'exigence de l'char[] d'alignement pourrait être différent d'un int, l'accès au-dessus de data par un int* pourrait ne pas être 'alignement sûr'. Cependant, étant donné que malloc() pour ne sont pas spécifiées renvoyer des pointeurs convenablement alignés pour tout type, ce qui suit ne devrait pas avoir de problèmes d'alignement:

int x; 
char* pData = malloc(4); 

if (!pData) exit(-1); 

fill_data(pData, 4); 

x = *(int*) pData; 

Cependant, notez que sizeof(int) pourrait ne pas être 4 et types int pourraient être little- ou Big- endian, donc il y a toujours des problèmes de portabilité avec le code ci-dessus - juste pas de problèmes d'alignement. Il existe d'autres façons d'effectuer des punitions de type y compris l'accès aux données par différents membres d'un union, mais ceux-ci peuvent avoir leurs propres problèmes de portabilité notamment l'accès à un membre qui n'était pas le dernier membre écrit est un comportement non spécifié.

+0

Votre dernier paragraphe n'est pas clair. Pouvez-vous élaborer? Merci! – Jay

+0

@Jay: J'ai développé le dernier paragraphe. Faites-moi savoir si cela ne clarifie toujours pas les choses. –

1

En général, cela n'aidera pas pour les variables locales. Il existe des règles d'optimisation qui peuvent être appliquées par le compilateur et des directives "pragma" supplémentaires qui pourraient être utilisées pour manipuler l'alignement.

0

Les problèmes de remplissage et d'alignement ne concernent que les structures, et non les variables locales, car le compilateur peut placer les variables locales dans l'ordre souhaité. En ce qui concerne l'importance des structures -

De nombreux compilateurs C alignent les membres struct en insérant des octets de remplissage entre eux. Par exemple, si vous avez une structure S {int a; char b; int c; char d; int e; }, et le matériel cible requiert que ints soit aligné sur des limites de 4 octets, alors le compilateur insérera trois octets de remplissage entre b et c et entre d et e, gaspillant 6 octets de mémoire par instance. D'autre part, si les membres étaient dans l'ordre ac, e, b, d, alors il insérera deux octets de remplissage à la fin (de sorte que la taille de S dans son ensemble est un multiple de 4, de sorte que les membres être correctement aligné dans les tableaux), ne gaspillant que 2 octets par instance. Les règles sont très spécifiques à la plateforme et au compilateur; Certains compilateurs peuvent réorganiser les membres pour éviter le remplissage, et certains ont des extensions pour contrôler les règles de remplissage et d'alignement au cas où vous auriez besoin d'une compatibilité binaire. En général, vous ne devez vous soucier de l'alignement que si vous lisez ou écrivez des structures directement et si elles ont la même disposition (ce qui est généralement une mauvaise idée), ou si vous pensez avoir beaucoup d'instances et que la mémoire prime .