Couler une structure en C dans une autre

J’ai deux structures C identiques (mais nommées différemment):

typedef struct { double x; double y; double z; } CMAcceleration; typedef struct { double x; double y; double z; } Vector3d; 

Maintenant, je veux affecter une variable CMAcceleration à une variable Vector3d (en copiant la structure entière). Comment puis-je faire ceci?

J’ai essayé ce qui suit, mais j’ai ces erreurs de compilation:

 vector = acceleration; // "incompatible type" vector = (Vector3d)acceleration; // "conversion to non-scalar type requested" 

Bien sûr, je peux avoir recours pour définir tous les membres individuellement:

 vector.x = acceleration.x; vector.y = acceleration.y; vector.z = acceleration.z; 

mais cela semble plutôt gênant.

Quelle est la meilleure solution?

C’est votre seule solution (à part l’envelopper dans une fonction):

 vector.x = acceleration.x; vector.y = acceleration.y; vector.z = acceleration.z; 

Vous pouvez réellement le lancer, comme ceci (en utilisant des pointeurs)

 Vector3d *vector = (Vector3d*) &acceleration; 

mais ce n’est pas dans les spécifications et donc le comportement dépend du compilateur, du temps d’exécution et du grand monstre de l’espace vert.

Vous pouvez utiliser un pointeur pour faire la conversion de type;

 vector = *((Vector3d *) &acceleration); 

Vous utilisez une fonction utilitaire pour cela:

 void AccelerationToVector( struct CMAcceleration* from, struct Vector3d* to ) { to->x = from->x; to->y = from ->y; to->z = from->z; } 

Pourquoi n’utilisez-vous pas

 typedef CMAcceleration Vector3d; 

(au lieu de créer une toute nouvelle structure)

dans ce cas, vector = acceleration; comstack très bien.

memcpy(&vector, &acceleration, sizeof(Vector3d));

Veuillez noter que cela ne fonctionne que si la disposition physique des structures en mémoire est identique. Cependant, comme l’a souligné @ Oli, le compilateur n’est pas obligé de s’en assurer!

Un moyen sûr (bien que quelque peu compliqué) de le faire serait d’utiliser un syndicat:

 union { CMAcceleration a, Vector3d v } tmp = { .a = acceleration }; vector = tmp.v; 

Les valeurs sont réinterprétées (depuis C99) lorsque le membre auquel on a accédé n’est pas le dernier. Dans ce cas, nous définissons l’accélération puis nous accédons au vecteur afin que l’accélération soit réinterprétée.

C’est ainsi que la fonction NSRectToCGRect est implémentée, par exemple.

Ceci est réalisé facilement grâce à une union :

 typedef struct { double x; double y; double z; } CMAcceleration; typedef struct { double x; double y; double z; } Vector3d; typedef union { CMAcceleration acceleration; Vector3d vector; } view; int main() { view v = (view) (Vector3d) {1.0, 2.0, 3.0}; CMAcceleration accel = v.acceleration; printf("proof: %g %g %g\n", accel.x, accel.y, accel.z); } 

Une autre version de la fonction utilitaire utilisant C99:

 static inline struct Vector3d AccelerationToVector(struct CMAcceleration In) { return (struct Vector3d){In.x, In.y, In.z}; } 

Lorsque l’optimisation du compilateur est activée (par exemple, -Os), cela ne devrait devenir absolument aucun code object lorsqu’il est appelé.