Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Extraire un short d'une chaine de caracteres

6 réponses
Avatar
nobody
Bonjour !

J'essaye sans trop de succès d'extraire un unsigned short d'un char*.
Petit boût de code :

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main(void)
{
char *data="ABCDEF";
unsigned short s;

printf("%d\n",sizeof(unsigned short));
s=(unsigned short)*(data+2);
printf("%x\n",s);
return 0;
}

quand je lance j'obtiens :
2
43

le programme ne semble extraire qu'un seul octet de la chaîne alors que je
souhaiterais en extraire deux soit le résultat
2
4344

un problème de cast ?
merci de votre aide

6 réponses

Avatar
Marc Boyer
Le 05-12-2006, a écrit :

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main(void)
{
char *data="ABCDEF";
unsigned short s;

printf("%dn",sizeof(unsigned short));
s=(unsigned short)*(data+2);
printf("%xn",s);
return 0;
}

quand je lance j'obtiens :
2
43

le programme ne semble extraire qu'un seul octet de la chaîne alors que je
souhaiterais en extraire deux soit le résultat
2
4344

un problème de cast ?


(data+2) est de type char*
*(data+2) est un char, et doit valoir 43.
Une fois convertit en unsigned short, 43 vaut toujours 43.

Pour ma part, je ferais plutot un
memcpy( &s, data+2, sizeof(s) );
après, ce que toi tu voulais faire, c'est peut être
s= *(unsigned short*)(data+2);
mais faut être sur que les contraintes d'alignement le permettent.

Marc Boyer
--
Si tu peux supporter d'entendre tes paroles
Travesties par des gueux pour exciter des sots
IF -- Rudyard Kipling (Trad. André Maurois)

Avatar
Pierre Maurette
Bonjour !

J'essaye sans trop de succès d'extraire un unsigned short d'un char*.
Petit boût de code :

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main(void)
{
char *data="ABCDEF";
unsigned short s;

printf("%dn",sizeof(unsigned short));
s=(unsigned short)*(data+2);


s=*((unsigned short*)data+2);

C'est le pointeur que vous devez transtyper, avant de le déréférencer.

Pour le reste, pas portable, endian, tout ça, je vous fous la paix...

--
Pierre Maurette

Avatar
Jean-Charles Gibier
wrote:

Bonjour !

J'essaye sans trop de succès d'extraire un unsigned short d'un char*.
Petit boût de code :

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main(void)
{
char *data="ABCDEF";
unsigned short s;

printf("%dn",sizeof(unsigned short));
s=(unsigned short)*(data+2);
printf("%xn",s);
return 0;
}

quand je lance j'obtiens :
2
43

le programme ne semble extraire qu'un seul octet de la chaîne alors
que je souhaiterais en extraire deux soit le résultat
2
4344

un problème de cast ?


Quand tu fais:
s=(unsigned short)*(data+2);
'Il' va prendre le char qui se trouve à l'adresse data + 2, le mettre

sous la forme d'un unsigned short, et c'est cela qui est printé en
hexa.
unsigned char *data="ABCDEF";
unsigned short s;

Si tu avais écrit
s = *((unsigned short *)(data + 2));
Cela ressemblerait plus à ce que tu veux, mais ce ne marcherait que par
hasard ainsi que t'on dit M. Boyer et P. Maurette, cela en raison de
problème d'alignement (ici sur une frontière de short) et d'endianness
(place des bytes dans un integer).



Je suis un peu rouillé en C et je m'y remets par nécessité.
Mais (tout pb d'alignement mis à part) est ce que l'offset du pointeur
ne serait pas plus juste comme ça ?

s = *((unsigned short *)(data + (2 * sizeof(unsigned short) ) ) );

ou
s = *(((unsigned short *)data) + 2) ;

ou alors il faut que je me replonge dans mes vieux bouquins ;-)


Avatar
Pierre Maurette
wrote:

Bonjour !

J'essaye sans trop de succès d'extraire un unsigned short d'un char*.
Petit boût de code :

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main(void)
{
char *data="ABCDEF";
unsigned short s;

printf("%dn",sizeof(unsigned short));
s=(unsigned short)*(data+2);
printf("%xn",s);
return 0;
}

quand je lance j'obtiens :
2
43

le programme ne semble extraire qu'un seul octet de la chaîne alors
que je souhaiterais en extraire deux soit le résultat
2
4344

un problème de cast ?


Quand tu fais:
s=(unsigned short)*(data+2);
'Il' va prendre le char qui se trouve à l'adresse data + 2, le mettre

sous la forme d'un unsigned short, et c'est cela qui est printé en
hexa.
unsigned char *data="ABCDEF";
unsigned short s;

Si tu avais écrit
s = *((unsigned short *)(data + 2));
Cela ressemblerait plus à ce que tu veux, mais ce ne marcherait que par
hasard ainsi que t'on dit M. Boyer et P. Maurette, cela en raison de
problème d'alignement (ici sur une frontière de short) et d'endianness
(place des bytes dans un integer).



Je suis un peu rouillé en C et je m'y remets par nécessité.
Mais (tout pb d'alignement mis à part) est ce que l'offset du pointeur ne
serait pas plus juste comme ça ?

s = *((unsigned short *)(data + (2 * sizeof(unsigned short) ) ) );

ou
s = *(((unsigned short *)data) + 2) ;

ou alors il faut que je me replonge dans mes vieux bouquins ;-)


J'avais fait une erreur dans ma suggestion. Au vu du résultat attendu,
il est clair que 2 représente pour l'OP un offset en char. J'aurais dû
proposer comme Harpo:
s=*((unsigned short*)(data+2));

Mais j'aurais peut-être préféré passer par le void*, qui pour moi
représente une adresse, et ne peut être déréférencé ni subir
l'arithmétique des pointeurs sans transtypage:

void* UneAdresse = data + 2;

puis:

unsigned short* UnPointeurUS = UneAdresse;
unsigned short s = *UnPointeurUS;

ou:

unsigned short s = *(unsigned short*)UneAdresse;


Noter que si on veut accéder à des unsigned short uniquement à des
offset multiples de sizeof(unsigned short), il sera plus simple de
faire:

char* data="ABCDEF";
unsigned short* dataShort = (unsigned short*)data;

et de travailler à partir de dataShort en arithmétique unsigned char.
On peut également faire:

unsigned short* dataShort = (unsigned short*)"ABCDEF";

ce qui, sans parler du boutisme, ne nous garantira pas plus un
alignement sur sizeof(unsigned char). Ça pourra être désastreux en
termes de performances, donc très décevant si on veut traiter des char
en parallèle pour justement aller plus vite.

--
Pierre Maurette



Avatar
Jean-Charles Gibier
wrote:

Bonjour !

J'essaye sans trop de succès d'extraire un unsigned short d'un char*.
Petit boût de code :

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main(void)
{
char *data="ABCDEF";
unsigned short s;

printf("%dn",sizeof(unsigned short));
s=(unsigned short)*(data+2);
printf("%xn",s);
return 0;
}

quand je lance j'obtiens :
2
43

le programme ne semble extraire qu'un seul octet de la chaîne alors
que je souhaiterais en extraire deux soit le résultat
2
4344

un problème de cast ?


Quand tu fais:
s=(unsigned short)*(data+2);
'Il' va prendre le char qui se trouve à l'adresse data + 2, le mettre

sous la forme d'un unsigned short, et c'est cela qui est printé en
hexa.
unsigned char *data="ABCDEF";
unsigned short s;

Si tu avais écrit
s = *((unsigned short *)(data + 2));
Cela ressemblerait plus à ce que tu veux, mais ce ne marcherait que par
hasard ainsi que t'on dit M. Boyer et P. Maurette, cela en raison de
problème d'alignement (ici sur une frontière de short) et d'endianness
(place des bytes dans un integer).



Je suis un peu rouillé en C et je m'y remets par nécessité.
Mais (tout pb d'alignement mis à part) est ce que l'offset du pointeur
ne serait pas plus juste comme ça ?

s = *((unsigned short *)(data + (2 * sizeof(unsigned short) ) ) );

ou
s = *(((unsigned short *)data) + 2) ;

ou alors il faut que je me replonge dans mes vieux bouquins ;-)


J'avais fait une erreur dans ma suggestion. Au vu du résultat attendu,
il est clair que 2 représente pour l'OP un offset en char.
[...]



Exact j'ai interprété. En fait l'OP exprime un offset de 2 en char pour
obtenir un offset de 1 en short.




Avatar
Moi


#include <unistd.h>


Pourquoi faire ?