Forum: Mikrocontroller und Digitale Elektronik Convert char array to float value


von Dev (Gast)


Lesenswert?

Hallo,

auf einem MSP430 soll ein char array in ein float Wert umgewandelt 
werden.
Der Hex-Wert: 0x3e200000 müsste in float 0.15625 dargestellt werden.
Der Wert ist ein ganz anderer. Ich kann jetzt nicht sehen, wo hier der 
Fehler liegen könnte.
1
void convert(char *Input, float*Output)
2
{       
3
    *Output= (float)((unsigned long)pDataSrc[0]
4
             + ((unsigned long)pDataSrc[1] << 8)
5
             + ((unsigned long)pDataSrc[2] << 16)
6
             + ((unsigned long)pDataSrc[3] << 24));   
7
}
1
Verwendung:
2
char Data[4];
3
Data[3] = 0x3E;
4
Data[2] = 0x20;
5
Data[1] = 0x00;
6
Data[0] = 0x00;
7
    
8
float Value;
9
    
10
convert(&Data[0], &Value);

von Udo S. (urschmitt)


Lesenswert?

Sicher dass die endianess stimmt?
https://de.wikipedia.org/wiki/Byte-Reihenfolge

von Dev (Gast)


Lesenswert?

Reihenfolge ist in Ordnung. Hab sogar die Byte Reihenfolge getauscht.

von k.A. (Gast)


Lesenswert?

Ein (unsigned) long ist eine ganze Zahl (ohne Vorzeichen).
Links shiften ist multiplizieren mit 2er Potenzen... aber es bleibt bei 
ganzen Zahlen
Ganze Zahlen addiert, bleiben ebenfalls ganze Zahlen.
... wie soll es hier zu einem Bruchteil einer Zahl kommen?

von Oliver S. (oliverso)


Lesenswert?

Was denkst du, was der cast (float) mit einem unsigned long macht, und 
was macht der tatsächlich?

Nebenfrage: wofür steht input in den Funktionsparametern?

Oliver

: Bearbeitet durch User
von Dirk B. (dirkb2)


Lesenswert?

Mit *((*float)(Input)) sollte es gehen.

Damit betrachtest du Input als float-Zeiger und derefenzierst ihn dann.

Die Endianess ist aber Systemabhängig, kann man aber mit einer 
Hilfsvariablen umgehen.

von Nop (Gast)


Lesenswert?

Dirk B. schrieb:
> Mit *((*float)(Input)) sollte es gehen.

Das ist undefined behaviour (pointer aliasing). Zwar darf ein 
char-Pointer alles aliasen, aber nicht alles darf einen char-Pointer 
aliasen.

Entweder, man macht type punning mit einer union, falls es in C ist (in 
C++: undefined behaviour), oder man macht es sauber mit memcpy, wobei 
der Compiler den Funktionsaufruf wegoptimieren wird:
1
memcpy(Output, Input, 4);

Man könnte auch noch nen static assert hinzufügen, ob float wirklich 4 
Bytes hat.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Angehängte Dateien:

Lesenswert?

Dev schrieb:
> Der Hex-Wert: 0x3e200000 müsste in float 0.15625 dargestellt werden.
Da muss nichts umgewandelt werden, denn das ist genau das selbe 
32-Bitmuster, nur einmal mit der float-Brille und einmal mit der 
hex-Brille angeschaut.

Siehe den Anhang mit der union.

von Stefan F. (Gast)


Lesenswert?

Dev schrieb:
> Der Hex-Wert: 0x3e200000 müsste in float 0.15625 dargestellt werden.

Ist das ein Intelligenz-Test?

von Nop (Gast)


Lesenswert?

Dirk B. schrieb:
> Mit *((*float)(Input)) sollte es gehen.

Übrigens noch eine Anmerkung, woran es ganz konkret knallen kann: ein 
char-Array braucht keinerlei Alignment, während je nach CPU ein Float 
auf vier Byte aligned sein muß. Es kann also bei dieser Konvertierung 
direkt zu einem Absturz mit Alignment-Fault kommen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.