Comment fonctionne cet alignement de taille

Je ne suis pas en mesure de comprendre le code ci-dessous en ce qui concerne le commentaire fourni. Qu’est-ce que ce code fait, et quel serait le code équivalent pour 8-aligned ?

 /* segment size must be 4-aligned */ attr->options.ssize &= ~3; 

Ici, ssize est de type unsigned int .

Puisque 4 en binary est égal à 100, toute valeur alignée sur des limites de 4 octets (soit un multiple de 4) aura les deux derniers bits mis à zéro.

3 en binary est 11, et ~ 3 est la négation au niveau du bit de ces bits, c’est-à-dire, … 1111100. Effectuer un bit AND avec cette valeur gardera tous les bits identiques, sauf les deux derniers qui seront effacés (bit & 1 == bit et bit & 0 == 0). Cela nous donne une valeur inférieure ou égale à un multiple de 4.

Pour effectuer la même opération pour 8 (1000 en binary), nous devons effacer les trois bits les plus bas. Nous pouvons le faire avec la négation au niveau du bit du binary 111, c’est-à-dire ~ 7.

Toutes les puissances de deux (1, 2, 4, 8, 16, 32 …) peuvent être alignées par une simple opération et.

Cela donne la taille arrondie:

 size &= ~(alignment - 1); 

ou si vous voulez arrondir:

 size = (size + alignment-1) & ~(alignment-1); 

L ‘”alignement-1″, tant que la valeur est une puissance de deux, vous donnera “tous les 1” jusqu’au bit juste sous la puissance de deux. ~ Inverse tous les bits, vous obtenez donc ceux pour les zéros et les zéros pour les uns.

Vous pouvez vérifier que quelque chose est une puissance de deux en:

 bool power_of_two = !(alignment & (alignment-1)) 

Cela fonctionne parce que, par exemple 4:

 4 = 00000100 4-1 = 00000011 & -------- 0 = 00000000 

ou pour 16 ans:

 16 = 00010000 16-1 = 00001111 & -------- 0 = 00000000 

Si on utilise 5 à la place:

 5 = 00000101 4-1 = 00000100 & -------- 4 = 00000100 

Donc pas une puissance de deux!

Peut-être un commentaire plus compréhensible serait

 /* make segment size 4-aligned by zeroing two least significant bits, effectively rounding down */ 

Alors au moins pour moi, une question immédiate me vient à l’esprit: faut-il vraiment arrondir à la taille, quand il est? Arrondir ne serait-il pas plus approprié:

 attr->options.ssize = (attr->options.ssize + 3) & ~3; 

Comme cela a déjà été dit dans d’autres réponses, pour qu’il soit aligné sur 8, 3 bits doivent être mis à zéro, utilisez donc 7 au lieu de 3 . Donc, nous pourrions en faire une fonction:

 unsigned size_align(unsigned size, unsigned bit_count_to_zero) { unsigned bits = (1 << bit_count_to_zero) - 1; return (size + bits) & ~bits; } 

~3 est le motif de bits ...111100 . Lorsque vous faites un bit AND avec ce motif, les deux bits inférieurs sont effacés, c’est-à-dire qu’ils arrondissent au multiple de 4 le plus proche.

~7 fait la même chose pour 8 alignés.

Le code assure la ssize deux derniers bits de la ssize , garantissant que ssize est un multiple de 4. Un code équivalent pour 8 alignés serait

 attr->options.ssize &= ~7; 
 number = number & ~3 

Le nombre est arrondi au multiple de 4 le plus proche qui est inférieur au number Ex:

  if number is 0,1,2 or 3, the `number` is rounded off to 0 

de même if number is 4,5,6,or 7, nombre is rounded off to 4

Mais si cela est lié à l’ alignement de la mémoire, celle-ci doit être alignée vers le haut et non vers le bas.