Parcours d'un tableau de char

Parcours d'un tableau de char - C - Programmation

Marsh Posté le 07-06-2006 à 08:50:43    

Bonjour, j'ai le soucis suivant :
J'ai un tableau de char qui représente le contenu d'une trame reçue avec un protocole quelconque.  
du style :
char toto[10]={0x00, 0x01, 0x02, 0x03 ......... 0x09}
 
Je veux faire un parcours de ce tableau remplir une structure.
Or dans cette structure, j'ai des char, des unsigned int, des unsigned long... enfin différents types quoi.  
 
Prenons le cas où le premier élément de ma structure est un unsigned long (4 octets).
Certes, je peux parcourir toto, élément par élément et faire des décalages de 8 bits à chaque char lu, par exemple :  
 
/****************************************************/
char toto[10]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09}
int i;
unsigned long MonLong=0;
for (i=0; i<4; i++)
{
 MonLong=MonLong<<8;             /*Pour i=0, on décale 0 de 8 bits, donc on a toujours 0*/
 MonLong=MonLong+toto[i];  
}
/****************************************************/
 
 
--> Certes, ca marche, mais je suppose qu'en faisant un cast, il y a moyen en une seule instruction d'affecter à MonLong les 4 premiers char.  
Est-ce que quelqu'un peut m'aider????
 
Merci
 

Reply

Marsh Posté le 07-06-2006 à 08:50:43   

Reply

Marsh Posté le 07-06-2006 à 09:36:10    

pierrot_lefou a écrit :


--> Certes, ca marche, mais je suppose qu'en faisant un cast, il y a moyen en une seule instruction d'affecter à MonLong les 4 premiers char.  


 
oui, mais attention
http://c-faq.com/strangeprob/ptralign.html

Reply

Marsh Posté le 07-06-2006 à 09:54:13    

Donc, l'autre solution serait de faire des :
MonLong=*(unsigned long *)toto;
 
puis de décaler mon pointeur de la taille de mon unsigned long (c'est à dire 4), mais je risque d'avoir crash avec le message "unaligned access"...
 
Donc, il vaut mieux que je reste avec mes décalages...  
 
 
OK, merci beucoup Skelter.

Reply

Marsh Posté le 07-06-2006 à 11:00:28    

Ce ne serait pas plus lisible comme ça

Code :
  1. char toto[10]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09}
  2. int i;
  3. unsigned long MonLong=0;
  4. for (i=0; i<4; i++)
  5. {
  6. MonLong<<=8;             /*Pour i=0, on décale 0 de 8 bits, donc on a toujours 0*/
  7. MonLong|=toto[i];
  8. }


 
En plus ça doit être un chouia plus rapide


Message édité par simple_stupid le 07-06-2006 à 11:00:45
Reply

Marsh Posté le 07-06-2006 à 15:59:23    

sauf que ton long il fait probablement 32 ou 64bits, alors tu vas pas aller bien loin ...

Reply

Marsh Posté le 07-06-2006 à 16:08:51    

pierrot_lefou a écrit :

J'ai un tableau de char qui représente le contenu d'une trame reçue avec un protocole quelconque.  
du style :
char toto[10]={0x00, 0x01, 0x02, 0x03 ......... 0x09}


Déjà, je conseille d'utiliser unsigned char pour ce genre de chose. C'est plus 'neutre'...

Citation :


Je veux faire un parcours de ce tableau remplir une structure.
Or dans cette structure, j'ai des char, des unsigned int, des unsigned long... enfin différents types quoi.  
 
Prenons le cas où le premier élément de ma structure est un unsigned long (4 octets).
Certes, je peux parcourir toto, élément par élément et faire des décalages de 8 bits à chaque char lu, par exemple :  
 
/****************************************************/
char toto[10]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09}
int i;
unsigned long MonLong=0;
for (i=0; i<4; i++)
{
 MonLong=MonLong<<8;             /*Pour i=0, on décale 0 de 8 bits, donc on a toujours 0*/
 MonLong=MonLong+toto[i];  
}
/****************************************************/
--> Certes, ca marche, mais je suppose qu'en faisant un cast, il y a moyen en une seule instruction d'affecter à MonLong les 4 premiers char.  


A condition d'utiliser unsigned int et d'être conforme à la spécification des octets du réseau, la solution que tu as utilisé est la seule qui soit portable. Je te conseille de t'y tenir.
 
En principe, on l'écrit directement en version 'déroulée. C'est plus efficace :  

Code :
  1. unsigned char buffer[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09};
  2.    unsigned long MonLong= 0;
  3.    unsigned offset = 2;
  4.    /* format 'reseau' : MSB en tete) */
  5.    MonLong |= buffer [offset + 0] << (8 * (3 - 0)); /* CORRECTION */
  6.    MonLong |= buffer [offset + 1] << (8 * (3 - 1));
  7.    MonLong |= buffer [offset + 2] << (8 * (3 - 2));
  8.    MonLong |= buffer [offset + 3] << (8 * (3 - 3));


on obtient : 0x02030405 dans MonLong.
 
sinon, on utilise ntohs() et ntohl() qui sont faits pour ça (en principe, livrés avec les sockets).


Message édité par Emmanuel Delahaye le 07-06-2006 à 18:51:04

---------------
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/
Reply

Marsh Posté le 07-06-2006 à 18:35:57    

Code :
  1. unsigned char buffer[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09};
  2.    unsigned long MonLong= 0;
  3.    unsigned offset = 2;
  4.    /* format 'réseau : MSB en tete) */
  5.    MonLong |= buffer [offset + 0] << (8 * 0);
  6.    MonLong |= buffer [offset + 1] << (8 * 1);
  7.    MonLong |= buffer [offset + 2] << (8 * 2);
  8.    MonLong |= buffer [offset + 3] << (8 * 3);


 
Moi j'obtiens:
0x5040302
 
Ce qui me paraît normal quand je regarde le code:
ton char le plus à gauche (0x02) est décalé de 0: on a donc: 0x00000002
ensuite on décale 0x03 de 8 et on l'ajoute: 0x0000302
ensuite, 0x04: 0x00040302
enfin, 0x05: 0x05040302
 
Non?

Reply

Marsh Posté le 07-06-2006 à 18:44:28    

simple_stupid a écrit :


Moi j'obtiens:
0x5040302


Ben oui, voilà ce qui arrive quand on ne prend pas le temps de vérifier. Merci, je corrige.


---------------
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/
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed