Pour tout type d'objet T
, est-ce toujours le cas que sizeof(T)
est au moins aussi grand que alignof(T)
?
Intuitivement, il semble que oui, car même lorsque vous ajustez l'alignement d'objets comme:
struct small {
char c;
};
au-dessus de ce qu'elle serait normalement, leur "taille" est également ajustée vers le haut de sorte que la relation entre les objets dans un tableau ait un sens tout en maintenant l'alignement (au moins dans mon testing . Par exemple:
struct alignas(16) small16 {
char c;
};
A à la fois une taille et un alignement de 16.
Au moins en C++ standard, pour tout ce dont vous pouvez faire un tableau (avec une longueur> 1), cela devra être vrai. Si tu as
Foo arr[2];
et alignof(Foo) > sizeof(Foo)
, puis arr[0]
et arr[1]
ne peuvent pas être alignés tous les deux.
Comme l'exemple de Zalman Stern montre, cependant, au moins certains compilateurs vous permettront de déclarer un type avec un alignement supérieur à sa taille, avec pour résultat que le compilateur ne vous laissera tout simplement pas déclarer un tableau de ce type. Ce n'est pas C++ conforme aux normes (il utilise des attributs de type, qui sont une extension GCC ), mais cela signifie que vous pouvez avoir alignof(T) > sizeof(T)
en pratique.
L'argument tableau suppose sizeof(Foo) > 0
, ce qui est vrai pour tout type pris en charge par la norme, mais o11c montre un exemple où les extensions du compilateur se cassent qui garantissent: certains compilateurs autorisent les tableaux de longueur 0, avec 0 sizeof
et positif alignof
.
#include <iostream>
typedef double foo __attribute__ ((aligned (64)));
alignas(64) double bar;
double baz __attribute__ ((aligned (64)));
int main(int argc, char *argv[]) {
std::cout << "foo sizeof: " << sizeof(foo) << " alignof: " << alignof(foo) << "\n";
std::cout << "bar sizeof: " << sizeof(bar) << " alignof: " << alignof(decltype(bar)) << "\n";
std::cout << "baz sizeof: " << sizeof(baz) << " alignof: " << alignof(decltype(baz)) << "\n";
}
Compiler avec:
clang++ -std=c++11 alignof_test.cpp -o alignof_test && ./alignof_test
Production:
foo sizeof: 8 alignof: 64
bar sizeof: 8 alignof: 8
baz sizeof: 8 alignof: 8
Donc, strictement parlant, non, mais l'argument ci-dessus concernant les tableaux doit être conservé.
Selon la norme c ++ 11 qui a introduit l'opérateur alignof
, sizeof
est définie comme suit (voir 5.3.3 expr.sizeof):
L'opérateur sizeof donne le nombre d'octets dans la représentation objet de son opérande
Alors que la définition de alignof
est (voir 5.3.6 expr.alignof):
Une expression alignof donne l'exigence d'alignement de son type d'opérande.
Puisque la définition de alignof
spécifie une exigence, éventuellement faite par l'utilisateur, plutôt qu'une spécification du langage, nous pouvons manipuler le compilateur:
typedef uint32_t __attribute__ ((aligned (64))) aligned_uint32_t;
std::cout << sizeof(aligned_uint32_t) << " -> " << alignof(aligned_uint32_t);
// Output: 4 -> 64
Modifié
Comme d'autres l'ont souligné, ces types ne peuvent pas être utilisés dans les tableaux, par exemple en essayant de compiler les éléments suivants:
aligned_uint32_t arr[2];
Résultats dans error: alignment of array elements is greater than element size
Étant donné que les tableaux nécessitent le type spécifié pour se conformer à la condition: sizeof(T) >= alignof(T)
De nombreux compilateurs autorisent les tableaux de taille 0
. L'alignement reste le même que l'alignement de l'élément unique.
(Entre autres choses, cela est utile pour forcer un alignement particulier dans les cas où vous ne pouvez pas utiliser un champ de bits)