Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1179 connectés 

  FORUM HardWare.fr
  Programmation
  C

  Probleme de taille de structure avec char[] et double

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Probleme de taille de structure avec char[] et double

n°1331776
ArthurDent
Posté le 24-03-2006 à 15:17:30  profilanswer
 

Bonjour,
 
J'ai un probleme bizarre,
 
si je declare :  

Code :
  1. struct cc{
  2.   char c[10];
  3.   double d;
  4. };


==>sizeof = 20, or je devrais avoir 18
 
si je fais :

Code :
  1. struct cc{
  2.   char c[10];
  3.   char d;
  4. };


==>sizeof = 11, ce qui est  cohérent
 

Code :
  1. struct cc{
  2.   double c;
  3.   double d;
  4. };


==>sizeof = 16, cohérent aussi
 
Le problème se pose donc si je met dans ma structure un char[] et un double ou un int.
 
J'aimerais donc savoir d'où viennent ces 2 octets en trop car cela posent des problèmes lorsque je veux transferer ma structure via une socket.
 
 
Merci d'avance.
 

mood
Publicité
Posté le 24-03-2006 à 15:17:30  profilanswer
 

n°1331777
Trap D
Posté le 24-03-2006 à 15:18:42  profilanswer
 

Problème de l'alignement des données 1,2,4,8 bytes.
Ce règle avec les options pragma pack, voir ton compilo.

n°1331782
Taz
bisounours-codeur
Posté le 24-03-2006 à 15:21:15  profilanswer
 

y a du padding insérer par ton compilateur. soit pour un accès plus rapide, soit par obligation d'alignement. donc si tu forces ton compilateur à ne pas le faire (pragma ou attribut), sois bien sur de ton coup.

n°1331784
skelter
Posté le 24-03-2006 à 15:25:01  profilanswer
 

il est aussi possible de compacter la structure dans un tableau de char si tu en as besoin

n°1331820
Taz
bisounours-codeur
Posté le 24-03-2006 à 15:52:17  profilanswer
 

???

n°1331834
skelter
Posté le 24-03-2006 à 16:00:00  profilanswer
 

si tu veux une image mémoire de ta structure dans laquel tu es sur que tout les champs sont contigues
ou inversement si tu veux lire une structure depuis une source externe (fichier) ou elle est compactée
 
ca evite de forcer l'alignement à la compilation (qui peux nuire aux performance) tout en gardant la possibilité de manipuler une version sans padding

n°1331902
Taz
bisounours-codeur
Posté le 24-03-2006 à 17:55:15  profilanswer
 

skelter a écrit :

si tu veux une image mémoire de ta structure dans laquel tu es sur que tout les champs sont contigues[quotemsg] donc pas une image mémoire :)
 
[quotemsg=1331834,6,88500]
ou inversement si tu veux lire une structure depuis une source externe (fichier) ou elle est compactée


 
bonjour la portabilité
 

skelter a écrit :


ca evite de forcer l'alignement à la compilation (qui peux nuire aux performance) tout en gardant la possibilité de manipuler une version sans padding

va-t-en surtout mal aligné un double sur sparc

n°1331907
Emmanuel D​elahaye
C is a sharp tool
Posté le 24-03-2006 à 18:04:44  profilanswer
 

Taz a écrit :

bonjour la portabilité
 
va-t-en surtout mal aligné un double sur sparc


Justement le mapping 'tableau de unsigned char' est garanti d'être portable. Ensuite on a une structure interne qui fait ce qu'elle peut et on recopie les champs 'à main' byte par byte en faisant les assemblages nécessaires à coup de | et de <<.
 
C'est sans doute pas rapide, mais c'est portable. Il suffit de fixer le format externe une fois pour toutes.

Message cité 2 fois
Message édité par Emmanuel Delahaye le 24-03-2006 à 19:02:16

---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
n°1331927
Sve@r
Posté le 24-03-2006 à 18:51:53  profilanswer
 

Emmanuel Delahaye a écrit :

Justement le mapping 'tableau de unsigned char' est garanti d'être portable. Ensuite on a une structure interne qui fait ce qu'elle peut et on recopie les champs 'à main' byte par byte en faisant les assemblages nécessaires à coup de | et de <<.
 
C'est sans doute pas rapide, mais c'est portable. Il suffit de fixer le format externe un fois pour toutes.


 
Il existe en php la fonction "serialize()" qui descend un objet dans une chaîne.
Ca y ressemble beaucoup non ?


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
n°1331956
nargy
Posté le 24-03-2006 à 20:16:13  profilanswer
 

> Il existe en php la fonction "serialize()" qui descend un objet dans une chaîne.
Ca y ressemble beaucoup non ?  
 
pas tout à fait... ici il s agit de traiter un double en chaîne binaire. serialize() convertit vraiment en chaîne de caractères.

mood
Publicité
Posté le 24-03-2006 à 20:16:13  profilanswer
 

n°1331972
skelter
Posté le 24-03-2006 à 20:43:55  profilanswer
 

Emmanuel Delahaye a écrit :

Justement le mapping 'tableau de unsigned char' est garanti d'être portable. Ensuite on a une structure interne qui fait ce qu'elle peut et on recopie les champs 'à main' byte par byte en faisant les assemblages nécessaires à coup de | et de <<.
 
C'est sans doute pas rapide, mais c'est portable. Il suffit de fixer le format externe une fois pour toutes.


 
absolument, en fait l'erreur par rapport à ce que sous entend Taz serait de traité naivement chaque champ à coup d'affectation ou de memcpy, l'interpretation ne serait pas la meme suivant l'endianess

n°1332004
ArthurDent
Posté le 24-03-2006 à 22:27:56  profilanswer
 

justement, le mapping dans un tableau ne m'est pas possible (c'est pour un TP et le prof veut absolument qu'on envoie la structure sur le socket pour voir les problemes d'endianess (communication entre x86 et SPARC))
 
je vais donc regarder du coté de pragma pack.
 

n°1332010
ArthurDent
Posté le 24-03-2006 à 22:43:59  profilanswer
 

bon ça marche avec  
 

Code :
  1. #pragma pack(push,1)
  2. struct s{
  3. ...
  4. };
  5. #pragma pack(pop)


 
par contre sur solaris gcc me balance un warning "pragma([push],[id],n) is not supported on this target", m'enfin bon ça marche c'est le principal.
 
Merci de votre aide


Message édité par ArthurDent le 24-03-2006 à 22:54:51
n°1332020
Taz
bisounours-codeur
Posté le 24-03-2006 à 23:00:15  profilanswer
 

pourquoi tu veux faire ça en fait ?

n°1332059
Sve@r
Posté le 25-03-2006 à 09:55:31  profilanswer
 

ArthurDent a écrit :

justement, le mapping dans un tableau ne m'est pas possible (c'est pour un TP et le prof veut absolument qu'on envoie la structure sur le socket pour voir les problemes d'endianess (communication entre x86 et SPARC))


 
Pas besoin d'une structure pour ça. Tu écris "short i=5", tu balances "i" sur ta socket et tu regardes ton nombre à l'arrivée. Normallement, tu devrais avoir 1280 (0x0005 est devenu 0x0500)
 
Ensuite tu pourras épater ton prof en lui disant que tout entier long ou court qui traverse un réseau doit d'abord être converti en "représentation réseau" via la fonction  

  • "htons()" => "host to net short" => converti un short du host vers le net
  • "htonl()" => "host to net long" => converti un long du host vers le net


Et tout nombre arrivant du réseau doit être reconverti en nombre compréhensible par la machine via la fonction:

  • "ntohs()" => "net to host short" => converti un short du net vers le host
  • "ntohl()" => "net to host long" => converti un long du net vers le host


Pour reprendre l'exemple, précédent, tu écris "short j=htons(i)", tu balances "j" sur le réseau que tu récupères de l'autre coté dans un "short x" et tu affiches "ntohs(x)". Tu devrais retrouver ton "5"


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
n°1332064
ArthurDent
Posté le 25-03-2006 à 10:32:33  profilanswer
 

Taz a écrit :

pourquoi tu veux faire ça en fait ?


 
je dois transferer ma structure via socket (sans mapping) entre une machine x86 et une SPARC et apparamment l'alignement par defaut des octets sur ces 2 machines n'est pas le meme, cela me créeait donc des decalages lorsque je voulais relire mes données coté SPARC (mon double etait decalé de 2 octets et donc le double que je lisais etait faux car ses 2 octets de poids fort correspondaient aux octets utilisés sur la x86 pour aligner et les 2 octets de poids faible correspondait aux octets de poids fort)
 

Sve@r a écrit :

Pas besoin d'une structure pour ça. Tu écris "short i=5", tu balances "i" sur ta socket et tu regardes ton nombre à l'arrivée. Normallement, tu devrais avoir 1280 (0x0005 est devenu 0x0500)
 
Ensuite tu pourras épater ton prof en lui disant que tout entier long ou court qui traverse un réseau doit d'abord être converti en "représentation réseau" via la fonction  

  • "htons()" => "host to net short" => converti un short du host vers le net
  • "htonl()" => "host to net long" => converti un long du host vers le net


Et tout nombre arrivant du réseau doit être reconverti en nombre compréhensible par la machine via la fonction:

  • "ntohs()" => "net to host short" => converti un short du net vers le host
  • "ntohl()" => "net to host long" => converti un long du net vers le host


Pour reprendre l'exemple, précédent, tu écris "short j=htons(i)", tu balances "j" sur le réseau que tu récupères de l'autre coté dans un "short x" et tu affiches "ntohs(x)". Tu devrais retrouver ton "5"


 
oui j'utilise ces 2 fonctions pour les int et les float, mias cela ne marche pas pour les doubles
 
et l'utilisation de structure m'est imposé

Message cité 1 fois
Message édité par ArthurDent le 25-03-2006 à 10:33:31
n°1332133
nargy
Posté le 25-03-2006 à 15:38:01  profilanswer
 

Il y a la librairie ``xdr`` de Sun pour les échanges réseaux normalisés (RFC1014).

n°1332180
ArthurDent
Posté le 25-03-2006 à 17:25:18  profilanswer
 

nargy a écrit :

Il y a la librairie ``xdr`` de Sun pour les échanges réseaux normalisés (RFC1014).


 
oui mais là aussi le tp nous "interdit" de  l'utiliser

n°1332188
nargy
Posté le 25-03-2006 à 17:39:53  profilanswer
 

:lol: ok il est pas sympa le prof :)

n°1332256
Sve@r
Posté le 25-03-2006 à 19:22:05  profilanswer
 

ArthurDent a écrit :

oui j'utilise ces 2 fonctions pour les int et les float, mias cela ne marche pas pour les doubles


 
C'est fun d'utiliser "ntohl()" et "htonl()" avec des float... mais puisque le prof t'intedit d'utiliser XDR il te suffit d'utiliser intelligemment "ntohs()" et "htons()" pour créer des fonctions "ntohd()" et "htond()"
 

Code :
  1. /* Fonction de conversion de double "local" en double "réseau" */
  2. double htond(
  3. double hostdbl)      /* Nombre à convertir */
  4. {
  5. /* Déclaration des variables */
  6. ushort i;       /* Indice de boucle */
  7. ushort j;       /* Indice de boucle */
  8. ushort convert;      /* Zone de conversion */
  9. union {
  10.  double val;      /* Stockage du nombre */
  11.  unsigned char p[8];     /* Décomposition du nombre */
  12. }zone;        /* Zone de travail */
  13. /* Remplisssage nombre à convertir */
  14. zone.val=hostdbl;
  15. /* Travail sur chaque extrémités de la zone en revenant vers le centre */
  16. for (i=0, j=7; i < j; i++, j--)
  17. {
  18.  /* Copie des parties de la zone dans un entier court de conversion */
  19.  convert=(zone.p[i] << 8) + zone.p[j];
  20.  /* Conversion de l'entier court par la primitive normalisée "htons" */
  21.  convert=htons(convert);
  22.  /* Recopie des octets de l'entier court dans les parties de la zone */
  23.  zone.p[i]=convert >> 8;
  24.  zone.p[j]=convert & 0x00ff;
  25. }
  26. /* Renvoi nombre converti */
  27. return(zone.val);
  28. }
  29. /* Fonction de conversion de double "réseau" en double "local" */
  30. double ntohd(
  31. double netdbl)      /* Nombre à convertir */
  32. {
  33. /* Déclaration des variables */
  34. ushort i;       /* Indice de boucle */
  35. ushort j;       /* Indice de boucle */
  36. ushort convert;      /* Zone de conversion */
  37. union {
  38.  double val;      /* Stockage du nombre */
  39.  unsigned char p[8];     /* Décomposition du nombre */
  40. }zone;        /* Zone de travail */
  41. /* Remplisssage nombre à convertir */
  42. zone.val=netdbl;
  43. /* Travail sur chaque extrémités de la zone en revenant vers le centre */
  44. for (i=0, j=7; i < j; i++, j--)
  45. {
  46.  /* Copie des parties de la zone dans un entier court de conversion */
  47.  convert=(zone.p[i] << 8) + zone.p[j];
  48.  /* Conversion de l'entier court par la primitive normalisée "ntohs" */
  49.  convert=ntohs(convert);
  50.  /* Recopie des octets de l'entier court dans les parties de la zone */
  51.  zone.p[i]=convert >> 8;
  52.  zone.p[j]=convert & 0x00ff;
  53. }
  54. /* Renvoi nombre converti */
  55. return(zone.val);
  56. }

Message cité 1 fois
Message édité par Sve@r le 25-03-2006 à 19:24:21

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
n°1332276
ArthurDent
Posté le 25-03-2006 à 19:53:40  profilanswer
 

Sve@r a écrit :

C'est fun d'utiliser "ntohl()" et "htonl()" avec des float... mais puisque le prof t'intedit d'utiliser XDR il te suffit d'utiliser intelligemment "ntohs()" et "htons()" pour créer des fonctions "ntohd()" et "htond()"
 

Code :
  1. /* Fonction de conversion de double "local" en double "réseau" */
  2. double htond(
  3. double hostdbl)      /* Nombre à convertir */
  4. {
  5. /* Déclaration des variables */
  6. ushort i;       /* Indice de boucle */
  7. ushort j;       /* Indice de boucle */
  8. ushort convert;      /* Zone de conversion */
  9. union {
  10.  double val;      /* Stockage du nombre */
  11.  unsigned char p[8];     /* Décomposition du nombre */
  12. }zone;        /* Zone de travail */
  13. /* Remplisssage nombre à convertir */
  14. zone.val=hostdbl;
  15. /* Travail sur chaque extrémités de la zone en revenant vers le centre */
  16. for (i=0, j=7; i < j; i++, j--)
  17. {
  18.  /* Copie des parties de la zone dans un entier court de conversion */
  19.  convert=(zone.p[i] << 8) + zone.p[j];
  20.  /* Conversion de l'entier court par la primitive normalisée "htons" */
  21.  convert=htons(convert);
  22.  /* Recopie des octets de l'entier court dans les parties de la zone */
  23.  zone.p[i]=convert >> 8;
  24.  zone.p[j]=convert & 0x00ff;
  25. }
  26. /* Renvoi nombre converti */
  27. return(zone.val);
  28. }
  29. /* Fonction de conversion de double "réseau" en double "local" */
  30. double ntohd(
  31. double netdbl)      /* Nombre à convertir */
  32. {
  33. /* Déclaration des variables */
  34. ushort i;       /* Indice de boucle */
  35. ushort j;       /* Indice de boucle */
  36. ushort convert;      /* Zone de conversion */
  37. union {
  38.  double val;      /* Stockage du nombre */
  39.  unsigned char p[8];     /* Décomposition du nombre */
  40. }zone;        /* Zone de travail */
  41. /* Remplisssage nombre à convertir */
  42. zone.val=netdbl;
  43. /* Travail sur chaque extrémités de la zone en revenant vers le centre */
  44. for (i=0, j=7; i < j; i++, j--)
  45. {
  46.  /* Copie des parties de la zone dans un entier court de conversion */
  47.  convert=(zone.p[i] << 8) + zone.p[j];
  48.  /* Conversion de l'entier court par la primitive normalisée "ntohs" */
  49.  convert=ntohs(convert);
  50.  /* Recopie des octets de l'entier court dans les parties de la zone */
  51.  zone.p[i]=convert >> 8;
  52.  zone.p[j]=convert & 0x00ff;
  53. }
  54. /* Renvoi nombre converti */
  55. return(zone.val);
  56. }



 
oué nan, j'ai rien dit pour les floats.
 
la fonction de conversion je l'ai fait a coup de memcpy en passant la taille de la donnée en parametre afin de pouvoir le reutiliser avec autre chose que des doubles

mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C

  Probleme de taille de structure avec char[] et double

 

Sujets relatifs
Problème lors d'insertion lignes dans tableau [résolu][Résolu] Probleme boucle toute simple pourtant
problème avec la fonction RangePetit problème de parse error
Probleme étrange avec realloc ...Probleme avec le validator du W3C
[PHP] *Resolu * Problème de chemin avec les "include"[C] Problème de pointeurs et d'allocation
XSL et taille des imagesCSS probleme de cascading avec les a:link, a:hover...
Plus de sujets relatifs à : Probleme de taille de structure avec char[] et double


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR