Dans son récent discours «Type punning en C ++ moderne», Timur Doumler a déclaré que std::bit_cast
cela ne peut pas être utilisé pour convertir un bit float
en un unsigned char[4]
car les tableaux de style C ne peuvent pas être renvoyés d'une fonction. Nous devons utiliser std::memcpy
ou attendre C ++ 23 (ou version ultérieure) lorsque quelque chose comme reinterpret_cast<unsigned char*>(&f)[i]
cela deviendra bien défini.
En C ++ 20, pouvons-nous utiliser un std::array
avec std::bit_cast
,
float f = /* some value */;
auto bits = std::bit_cast<std::array<unsigned char, sizeof(float)>>(f);
au lieu d'un tableau de style C pour obtenir des octets d'un float
?
struct X { unsigned char elems[5]; };
satisfait la règle que vous citez. Il peut certainement être initialisé par liste avec jusqu'à 4 éléments. Il peut également être initialisé par liste avec 5 éléments. Je ne pense pas qu'un implémenteur de bibliothèque standard déteste suffisamment les gens pour le faire, mais je pense que c'est techniquement conforme.elems[5]
. Et à ce stade, je ne vois pas comment vous pourriez vous retrouver avec un agrégat oùsizeof(array<char, sizeof(T)>) != sizeof(T)
?struct X { unsigned char c1, c2, c3, c4; };
oustruct X { unsigned char elems[4]; };
- si , tandis que les caractères doivent être les éléments de cet ensemble, ce qui leur permet d'être soit des éléments globaux directs ou des éléments d'un sous-agrégat unique.P -> Q
n'implique rien sur le cas où!P
array
lui - même n'aura pas de remplissage. Les implémentations de celui-ci peuvent ne pas avoir de remplissage (et toutes les implémentations qui doivent l'être doivent être considérées comme dysfonctionnelles), mais il n'y a aucune garantie quearray
cela ne le sera pas.La réponse acceptée est incorrecte car elle ne prend pas en compte les problèmes d'alignement et de remplissage.
Par [tableau] / 1-3 :
La norme n'exige pas réellement
std::array
d'avoir exactement un membre de données publiques de typeT[N]
, donc en théorie il est possible quesizeof(To) != sizeof(From)
ouis_trivially_copyable_v<To>
.Je serai cependant surpris si cela ne fonctionne pas dans la pratique.
la source
Oui.
Selon l' article qui décrit le comportement de
std::bit_cast
, et sa mise en œuvre proposée dans la mesure où les deux types ont la même taille et sont copiables, la distribution devrait réussir.Une implémentation simplifiée de
std::bit_cast
devrait ressembler à:Depuis un flotteur (4 octets) et un tableau de
unsigned char
parsize_of(float)
rapport à tous ceux affirme, le sous - jacentstd::memcpy
sera exécuté. Par conséquent, chaque élément du tableau résultant sera un octet consécutif du flottant.Afin de prouver ce comportement, j'ai écrit un petit exemple dans l'explorateur du compilateur que vous pouvez essayer ici: https://godbolt.org/z/4G21zS . Le flottant 5.0 est correctement stocké sous la forme d'un tableau d'octets (
Ox40a00000
) qui correspond à la représentation hexadécimale de ce nombre flottant dans Big Endian .la source
std::array
est garanti de ne pas avoir de bits de rembourrage, etc.?auto bits = reinterpret_cast<std::array<unsigned char, sizeof(float)>&>(f)
et obtenir exactement la même sortie. Cela prouve-t-il quelque chose?std::array
satisfait aux exigences de ContiguiosContainer (depuis C ++ 17) .std::vector
répond également aux mêmes critères et ne peut évidemment pas être utilisé ici. Y a-t-il quelque chose qui nécessite destd::array
contenir les éléments à l'intérieur de la classe (dans un champ), l'empêchant d'être un simple pointeur vers le tableau interne? (comme dans le vecteur, qui a également une taille, que le tableau ne nécessite pas d'avoir dans un champ)std::array
efficacement à stocker les éléments à l'intérieur, mais je m'inquiète des problèmes de mise en page.