Bonjour,
Je dois convertir une chaine de 4 car représentant les 4 bytes d'un float
en float.
Je cherche mais ne trouve pas
Merci de vos conseils.
Alfy
Version imprimable
Bonjour,
Je dois convertir une chaine de 4 car représentant les 4 bytes d'un float
en float.
Je cherche mais ne trouve pas
Merci de vos conseils.
Alfy
Salut,
Il y a des problèmes d'alignement et d'endianess qui font que tu ne peux pas caster directement pour considérer l'adresse de ta chaine comme celle d'un float. Dans l'exemple ci dessous, on écrase le float avec la chaine "\x00\x00\x00\x00". Le premier caractère '-' n'est là que pour sensibiliser au problème d'alignement résolu par le memcpy. L'endianess n'est pas résolu, mais comme on ne sait pas d'où sort ton char[4]...
Si tu es sûr de l'alignement et de l'endianness, tu peux faire directementCode:
1
2
3
4
5
6
7
8
9
10
11 #include <stdio.h> #include <string.h> int main(void) { char input[] = "-\x00\x00\x00\x00"; float value = 1234.56; memcpy(&value, &(input[1]), 4); printf("%f\n", value); return 0; }
A+Code:
1
2
3
4
5
6
7
8 #include <stdio.h> int main(void) { char input[] = "\x00\x00\x00\x00"; printf("%f\n", (float)*input); return 0; }
Pfeuh
Merci Pfeuh, je pense que c'est bien la solution
Je cherchais une fonction, mais elle ne doit pas exister.
Alfy
Le souci c'est que les 4 bytes du float sont contenus dans une chaine de 4 car.
bit 0-22 = mantisse, 23-30 exposant, 31 signe
Ce n'est pas la représentation du nombre en string mais son codage.
Donc je ne pense pas que strtof soit approprié ou je me tropme
Alfy
Je pense que tu n'as pas compris ce que veux le PO. il ne veut pas transformer la chaine "1234.56" en float 1234.56. Il veux transformer la chaine de 4 caractères qui contient en fait les 4 bytes d'un float32 en un float32. Par exemple la chaine "\000\000\000\000" (ou encore [0, 0, 0, 0]) en 0.00. comme on ne sait pas d'où vient cette chaine et qu'elle peut être une partie d'une autre chaine, je persiste à dire qu'il peut y avoir un problème d'alignement. Et strtof ne fait pas ce que veux le PO
Je crois qu'il faudrait que tu expliques un peu mieux ton problème et nous donne un exemple de chaine à convertir ;)
@pfeuh : la représentation d'un float32 est telle fixe ? Autant un entier c'est facile, autant un float....
Pour info, voilà mon problème
Je recois une chaine (connexion à un onduleur photovoltaique) qui me donne ceci
Byte 0 -état de la transmission
Byte 1 -état de l'onduleur
Byte 2 -V3
Byte 3 -V2
Byte 4 -V1
Byte 5- V0
Byte 6- CRC low
Byte 7- CRC high
Les 4 bytes V3..V0 représentent un nombre float
pour retrouver sa valeur originale il est nécessaire de mettre en séquence les 4 bytes et de les lire comme un nombre float 32 bits (normes ANSI)
(traduction libre de la doc)
La notion de big ou little endian n'est pas indiquée, mais le test est vite fait dans la mesure ou je peux tester le résultat et le comparer à ce que la machine affiche sur son display.
exemple
recu 00 06 45 2d b6 32 9c 34
donc - 45 2d b6 32 - qui doit donner un float de valeur 2779.387207
Alfy
J'ai fait un code qui fait le taff :
Mais j'ai de gros doutes sur la robustesse....Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 int main (void) { printf("sizeof(float) = %d\n" "sizeof(int) = %d\n" "sizeof(long) = %d\n", sizeof(float), sizeof(int), sizeof(long) ); char *chaine = "452db632"; unsigned long hexa = strtoul(chaine, 0, 16); printf("hexa = %X\n", hexa); float *pt = (float*)&hexa; float nombre = *pt; printf("nombre = %f\n", nombre); return 0; }
Ok c'est tout a fait cela
Je me doutais que c'était un peu ambigü a expliquer comme problème
Alfy
Il faudra tester sur ta machine cible, le code se base sur le fait qu'un float et un long occupe le même nombre d'octets (4 sous Windows XP). Tu nous diras si ça marche bien.
Oui cela fonctionne, je suis sous Linux et c'est 4 aussi
Merci bcp
Alfy
En gros oui, il y a un standard, le IEEE je ne sais plus combien. Je dis en gros parce que qu'il y a toujours les histoires d'endianess. J'ai échangé des floats32 entre des cartes à 8031, à pic24, à pic32, à arm 32 et un PC sans aucun problème. En C, bien sûr, mais aussi en python pour le PC.
C'est surtout sur une machine 64 bits que ça risque de partir en vrille. Si tu es restes sur du 32 bits, ça devrait aller. De rien pour le coup de main ^^
http://en.wikipedia.org/wiki/IEEE_754-1985
Je présume que c'est celui-ci. Il y a effectivement la question de l'endianess, il se trouve que dans le cas du PO ça tombe dans le bon sens.
Je reviens vers vous pour ce problème
J'ai donc une chaine représentant un float
- char *chaine = "\x45\x2d\xb6\x32";
et ai initialisé 4 bytes pour le float
- float energie;
Je veux a présent que l'adresse du float soit l'adresse de chaine
mais tous mes essais sont restés vains
Merci
Alfy
C'est tout simplement impossible.
Si tu déclares deux entiers de type int, il te parait évident qu'ils seront à deux emplacements différents dans la mémoire et que donc les adresses seront différentes ?
Il n'est donc pas possible qu'un objet float et qu'un objet char* aient la même adresse. En revanche, tu peux créer un pointeur sur float et lui donner comme valeur l'adresse de la chaine :
Rien ne te garantit par contre que l'interprétation des 4 octets de chaine via le pointeur p_energie donne un résultat probant.Code:
1
2
3
4
5
6
7
8
9
10 int main(void) { char *chaine = "\x45\x2d\xb6\x32"; float *p_energie = chaine; printf("'%s' a l'adresse %p\n", chaine, chaine); printf("'%f' a l'adresse %p\n", *p_energie, p_energie); return 0; }