30 votes

Puis-je convertir en toute sécurité la structure des flottants en tableau flottant en C ++?

Par exemple, j'ai cette structure

 struct  A {
    float x;
    float y;
    float z;
};
 

Puis-je faire ceci? A a; float* array = (float*)&a; Et utiliser un tableau flottant?

27voto

Thomas Matthews Points 19838

Non, le transtypage d'un struct vers un tableau ne fonctionnera pas. Les compilateurs sont autorisés à ajouter du remplissage entre les membres.

Les tableaux n'ont pas de remplissage entre les membres.

Remarque : rien ne vous empêche de lancer une conversion, cependant, l'utilisation de la valeur après la conversion entraîne un comportement indéfini.

24voto

Sil Points 401

Dans un sens pratique, oui vous pouvez le faire et il fonctionne dans tous les plus utilisés, les architectures et les compilateurs.

Voir "Typique de l'alignement de la C structures sur x86" l'article sur Wikipédia.

Plus de détails:

  • les flotteurs sont de 4 octets et pas de rembourrage sera inséré (dans pratiquement tous les cas).

  • aussi la plupart des compilateurs avez la possibilité de spécifier l'emballage des structures et vous pouvez le faire valoir aucun remplissage n'est inséré( c'est à dire #pragma pack de visual studio )

  • les tableaux sont garantis pour être contigus en mémoire.

Pouvez-vous garantir qu'il fonctionnera dans tous les Processeurs dans le monde, avec tous les compilateurs? Non.. mais j'ai vraiment envie de voir une plate-forme en cas d'échec :)

EDIT: ajout d' static_assert(sizeof(A) == 3*sizeof(float)) feront de ce code compile pas si il y a des octets de remplissage. Alors vous serez sûr qu'il fonctionne lorsqu'il compile.

19voto

StoryTeller Points 6139

Il s'agit d'une violation d'alias stricte, simple et claire. Tout accès avec ce pointeur, à tout élément sauf le premier, est un comportement indéfini dans votre cas. Et dans des cas plus complexes, il s'agit simplement d'un comportement indéfini quel que soit l'élément auquel vous accédez.

Si vous avez besoin d'un tableau, utilisez un tableau. std::array également une surcharge pour std::get , vous pouvez donc l'utiliser pour nommer chaque membre du groupe:

 using A = std::array<float, 3>;

enum AElement { X, Y, Z };

int main() {
  A a;
  get<X>(a) = 3.0f; // sets X;

  float* array = a.data(); // perfectly well defined
}
 

6voto

Pavel Points 157

Pour g ++, vous pouvez utiliser un attribut pour votre structure, comme ceci:

 struct  A {
    float x;
    float y;
    float z;
}__attribute__((__packed__));
 

C'est désactiver l'alignement des structures.

4voto

gnasher729 Points 5011

Vous pouvez le faire, jusqu'à ce que le compilateur commence l'optimisation, et puis les choses vont mal.

Accès à tout, mais le premier élément d'une structure à l'aide d'un pointeur vers le premier élément est un comportement indéterminé. "Comportement indéfini" signifie que tout peut arriver. Le compilateur peut supposer qu'il n'existe pas de comportement indéfini.

Il y a beaucoup de conséquences que le compilateur peut en déduire que: Si le compilateur sait que votre float* pointe vers le premier élément de la structure, on peut en déduire que tous les index de ce tableau est égal à 0 (car tout le reste est un comportement indéterminé). Si le compilateur ne sait pas cela, alors on peut en déduire que le pointeur sur le tableau ne peut pas pointer à la structure, et la modification des éléments d'un tableau ne peut pas changer des éléments struct et vice versa.

Pouvez-vous voir comment cela va mal se passer?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X