Forum: PC-Programmierung Typumwandelung: float <---> char*


von Cnewbie (Gast)


Lesenswert?

Hallo, da ich für die Verarbeitung von Daten auf einem Mikrocontroller 
Variablen vom Typ float, integer und char verwende, benötige ich 
Funktionen mit denen ich die Typen umwandeln kann.

Z.B. flott umwandeln in char* oder char* in float

Mit den sprintf sowie sscanf Funktionen hab ich dies schon versucht.
char* in float kann ich umwandeln, nur nicht umgekehrt. Gibt es eine 
Funktion mit der ich dies tun kann?

von Christian R. (supachris)


Lesenswert?

Was für einen Sinn macht es, einen Pointer auf eine 8-Bit-Variable in 
eine float-Variable zu wandeln? Und umgekehrt?
Was willst du denn genau machen?

Normal brauchst du das nur zu Casten, aber bei Float -> Char wirds schon 
sinnbefreit, weil float ja meinetwegen 12.45678 als Wert hat, char aber 
nur einen Wertebereich zwischen -128 und +127 in ganzen Zahlen.

von Cnewbie (Gast)


Lesenswert?

Ich möchte einen float Wert Beispiel 12.3456 in ein char Array ablegen.
4 Bytes (char) entsprechen ja einem float Wert.
Wie kann ich es hinbekommen, dass ich einen float Wert in 4 Bytes 
ablegen kann und umgekehrt?

von Cnewbie (Gast)


Lesenswert?

1 Byte sind 8 Bit

4 Bytes entspricht einem 32 Bit Wert. Der 32 Bit Wert ist ja ein float 
Wert.

von Cnewbie (Gast)


Lesenswert?

Mit atoi und atof kann ich einen String in Integer und Float umwandeln.
Nur umgekehrt funktioniert es mit dem 8 Bit Mikrocontroller nicht.

von Cnewbie (Gast)


Lesenswert?

Hallo..........

von Rolf Magnus (Gast)


Lesenswert?

Es ist unklar, was du nun willst. Einen float in einen char* umwandeln 
wohl nicht, denn das ist ziemlich sinnfrei. Wohin sollte denn das 
Bitpattern eines float, wenn man es als Zeiger interpretiert, zeigen?
Du schreibst was von sprintf und sscanf, was nahelegt, daß du eine 
Stringrepräsentation des Wertes haben willst. Dann aber schreibst du:
"4 Bytes (char) entsprechen ja einem float Wert. Wie kann ich es 
hinbekommen, dass ich einen float Wert in 4 Bytes ablegen kann und 
umgekehrt?", was eher darauf hinweist, daß du den float-Wert als Array 
aus Bytes interpretieren willst, z.B. um es als Binärdaten irgendwo 
hinzusenden. In dem Fall wäre sprintf/sscanf die falsche Wahl.
Also, was willst du?

von Uhu U. (uhu)


Lesenswert?

Was hast du denn ausprobiert?

von Cnewbie (Gast)


Lesenswert?

Ja ich möchte einen float-Wert als Array aus Bytes interpretieren, z.B. 
um es als Binärdaten irgendwo hinzusenden.
Das meinte ich auch. Hab ich sehr schlecht ausgedrückt. Ich bitte um 
Entschuldigung.

von Cnewbie (Gast)


Lesenswert?

Gibt es schon dafür Funktionen?

von Balu (Gast)


Lesenswert?

Das würde mich auch interessieren, wie das geht.
Hab es bisher noch nicht hinbekommen.

von Jorge (Gast)


Lesenswert?

>Ja ich möchte einen float-Wert als Array aus Bytes interpretieren, z.B.
>um es als Binärdaten irgendwo hinzusenden.

Ich glaube dafür brauchst du keine Funktion, da reicht wie schon erwähnt 
ein typecast oder man sogar darauf noch verzichten.

...


float fv=3.1415f;
float fc;

char *fewbytes=(char *) &fv;
...


#include <mem.h>

main() {
  float fv=3.1415f;
  float destination;

  memcpy(&destination,&fc,sizeof(fv));


}

von Cnewbie (Gast)


Lesenswert?

char array[10];

void FloatToString(float fvalue,char* buf)
{
int i;
unsigned char charPtr;

for (i=0;i<4;i++)
   {
  charPtr = *((char*)fvalue+i);
  buf[3+3-i] =charPtr;
   }
}

void main (void)
{
 ....
 FloatToString(12.3456,array);
 ....
}

Dies müsste doch so gehen oder? Im array sind dann 4 Bytes enthalten.
Ich hab die Funktion nicht getestet.

von Rolf Magnus (Gast)


Lesenswert?

Genau zu dem Thema gab's gerade erst einen Thread.
Siehe Beitrag "Float to Raw Bytes"

von Uhu U. (uhu)


Lesenswert?

Cnewbie wrote:
> Dies müsste doch so gehen oder?

Garantiert nicht.

von Rolf Magnus (Gast)


Lesenswert?

Gehen wir das mal durch:

> void FloatToString(float fvalue,char* buf)

Wieso heißt die Funktion "FloatToString"? Sie soll doch gar keinen 
String erzeugen.

>  charPtr = *((char*)fvalue+i);

Das ist ziemlicher Unsinn, und zwar in jedem Detail. Zuerst werden die 
Bits, aus denen fvalue zusammengesetzt ist, als Zeiger interpretiert. 
Dan wird dieser Zeiger um i erhöht. Danach wird das Byte gelesen, auf 
das dieser zeigt. Das was dort steht, wird dann wieder in einen Zeiger 
umgewandelt und charPtr zugewiesen.

>  buf[3+3-i] =charPtr;

Hier auch wieder das Byte, das an dem angegebenen Index steht, mit dem 
Zeigerwert (und nicht dem Wert der Speicherstelle, auf die er zeigt) 
gefüllt. Übrigens: Wie bist du beim Index auf 3+3-i gekommen? Damit 
schreibst du hinter das Ende des Arrays.

> void main (void)

main muß int zurückliefern.

von Cnewbie (Gast)


Lesenswert?

void FloatToCharArray(float fvalue)
{
unsigned char buf[5];
int i;
unsigned char charPtr;

for (i=0;i<4;i++)
   {
     charPtr = *((unsigned char*)fvalue+i);
     buf[3-i] =charPtr;
   }
}

void main (void)
{
 ....
 FloatToCharArray(12.3456);
 ....
}

So Funktioniert die Funktion. In buf[0] bis buf[3] stehe dann die Werte 
drin.
Wie kann ich den buffer buf zurückgeben, so dass ich dann die Werte 
außerhalb verwenden kann?

Wie wandelt man nun die 4 Bytes wirder um in einen Float Wert?

von Rolf Magnus (Gast)


Lesenswert?

> So Funktioniert die Funktion.

Mit Sicherheit nicht. Du interpretierst immer noch einen Float als 
Adresse. Hast du die Diskussion gelesen, auf die ich verlinkt habe?

> Wie wandelt man nun die 4 Bytes wirder um in einen Float Wert?

Auch das hättest du der verlinkten Diskussion entnehmen können.

von Cnewbie (Gast)


Lesenswert?

void FloatToCharArray(float fvalue)
{
unsigned char buf[5];
int i;
unsigned char charPtr;

for (i=0;i<4;i++)
   {
     charPtr = *((unsigned char*)&fvalue+i);
     buf[3-i] =charPtr;
   }
}

void main (void)
{
 ....
 FloatToCharArray(12.3456);
 ....
}

Ich Adressoperator & vor der Variable fvalue vergessen.

>>Auch das hättest du der verlinkten Diskussion entnehmen können.

Also diese Diskussion hat mir nicht sonderlich viel geholfen

von Cnewbie (Gast)


Lesenswert?

Also ich finde, es wird darum so ein großes Geheimnis gemacht.

von Rolf Magnus (Gast)


Lesenswert?

> Also diese Diskussion hat mir nicht sonderlich viel geholfen

Dann zitiere ich mal den wesentlichen Teil:
1
float tmpBuffer;
2
char* buffer = (char*)&tmpBuffer;

Das wäre ohne Kopieren. Wenn du die Bytes kopieren willst:
1
memcpy(buf,f,sizeof(f);

Hier ist f die float-Variable und buf ein 4 Bytes großes char-Array.
die beiden Varianten drehen allerdings die Reihenfolge der Bytes nicht 
um. Wenn du das willst, ist deine Variante in Ordnung.
Mir ist gerade erst aufgefallen, daß ich oben zum Teil was Falsches 
geschrieben hab, weil ich angenommen hatte, charPtr sei ein Zeiger auf 
char. Der Name ist etwas unglücklich gewählt.
Dein Code sieht jetzt ok aus. Warum ist buf jetzt 5 Bytes groß?
Zur Ausgabe des Puffers: Den kannst du aus der Funktion nicht rausgeben, 
weil er nur solange existiert, wie die Funktion ausgeführt wird. 
Stattdessen kann aber der Aufrufer den Puffer anlegen und einen Zeiger 
darauf an die Funktion übergeben. Also so wie du es am Anfang mal 
gemacht hast.

von Cnewbie (Gast)


Lesenswert?

So meinst du das?
1
unsigned char array[10];
2
3
void FloatToString(float fvalue,char* buf)
4
{
5
int i;
6
unsigned char charPtr;
7
8
for (i=0;i<4;i++)
9
   {
10
     charPtr = *((unsigned char*)&fvalue+i);
11
     buf[3-i] =charPtr;
12
   }
13
}
14
15
void main (void)
16
{
17
 ....
18
 FloatToString(12.3456,array);
19
 ....
20
}

Mit dieser Zeile kann ich dann den float Wert in ein char Array (4 
Bytes) kopieren? Welche Header Datei muss ich hierfür noch zusätzlich 
includen?
1
memcpy(buf,f,sizeof(f);

von Cnewbie (Gast)


Lesenswert?

So meinst du das?
1
unsigned char array[10];
2
3
void FloatToCharArray(float fvalue,char* buf)
4
{
5
int i;
6
unsigned char charPtr;
7
8
for (i=0;i<4;i++)
9
   {
10
     charPtr = *((unsigned char*)&fvalue+i);
11
     buf[3-i] =charPtr;
12
   }
13
}
14
15
void main (void)
16
{
17
 ....
18
 FloatToCharArray(12.3456,array);
19
 ....
20
}

Mit dieser Zeile kann ich dann den float Wert in ein char Array (4
Bytes) kopieren? Welche Header Datei muss ich hierfür noch zusätzlich
includen?
1
memcpy(buf,f,sizeof(f);

von Cnewbie (Gast)


Lesenswert?

Zum Testen, hab verwende ich die Software Microsoft Visual Studio 6.0 
C++.
Folgende Fehlermeldungen erhalte ich beim comilieren:

>warning C4305: '=' : Verkuerzung von 'const double' in 'float'

>error C2664: 'memcpy' : Konvertierung des Parameters 2 von 'float' in 'const 
>void *' nicht moeglich
1
unsigned char buf[4];
2
float f;
3
f=12.3456;
4
5
memcpy(buf,f,sizeof(f));
6
printf("buf[0]: %c, buf[1]: %c, buf[2]: %c, buf[3]:  %c\n",buf[0],buf[1],buf[2],buf[3]);

von Rolf Magnus (Gast)


Lesenswert?

> So meinst du das?

Ja, wobei für dein Array 4 gereicht hätten, also
1
unsigned char array[4];

oder gar
1
unsigned char array[sizeof(float)];

> Mit dieser Zeile kann ich dann den float Wert in ein char Array (4
> Bytes) kopieren?

Ich bin wohl noch nicht ganz wach. Ich hab übersehen, daß die Zeile so 
nicht richtig ist. Aber im Prinzp ja. Wie gesagt werden dabei allerdings 
die Bytes nicht umgedreht, so wie du es in deinem Code machst.

> Welche Header Datei muss ich hierfür noch zusätzlich includen?

<string.h>

In deiner Funktion müßte die Zeile so aussehen:
1
memcpy(buf, &fvalue, sizeof fvalue);

von Rolf Magnus (Gast)


Lesenswert?

>warning C4305: '=' : Verkuerzung von 'const double' in 'float'

Das kommt, weil 12.3456 vom Typ const double ist. Die Warnung kannst du 
wegbekommen, indem du daraus 12.3456F machst. Dann ist der Wert 
derselbe, aber der Typ ist const float.

>error C2664: 'memcpy' : Konvertierung des Parameters 2 von 'float'
> in 'const void *' nicht moeglich

Das kommt, weil beim zweiten memcpy-Parameter ein & fehlt. Mea culpa.

von Cnewbie (Gast)


Lesenswert?

Danke!

Wie kann ich nun die 4 Bytes in ein float Wert wandeln?

von Cnewbie (Gast)


Lesenswert?

Die Umwandlung von float in 4 Bytes sowie 4 Bytes in float funktioniert.
1
// convert float to char array
2
unsigned char buf[4];
3
float f1=(float)12.3456;
4
memcpy(buf,&f1,sizeof(f1));
5
6
// convert char array to float
7
float f2;
8
memcpy(&f2,buf,sizeof(buf));
9
printf("f2: %lf\n",f2);

von StinkyWinky (Gast)


Lesenswert?

Das könnte man doch auch mit einer union machen.

von Uhu U. (uhu)


Lesenswert?

@StinkyWinky:
Jetzt mach den armen Cnewbie nicht noch konfuser...

@Cnewbie:
Dir würde ich dringend empfehlen, ein C-Tutorial für Anfänger Schritt 
für Schritt durchzuarbeiten und die Beispiele auch wirklich zu 
programmieren. Anders wird das nämlich nichts.

> Dies müsste doch so gehen oder? ... Ich hab die Funktion nicht getestet.

Solche Aussagen getraue ich mir selbst nach 20 Jahren C-Erfahrung nicht.

von Cnewbie (Gast)


Lesenswert?

Du bist echt so ein Großkotz Uhu Uhuhu!


Dieser Code funktioniert prima.

unsigned char array[10];

void FloatToCharArray(float fvalue,char* buf)
{
int i;
unsigned char charPtr;

for (i=0;i<4;i++)
   {
     charPtr = *((unsigned char*)&fvalue+i);
     buf[i] =charPtr;
   }
}

Wenn ich nun 4 Bytes in ein float Wert umwandeln möchte und zwar so 
ähnlich wie die obige Funktion, wie müsste man diese realisieren?

von Guile L. (sphinx)


Lesenswert?

CNewbie es gibt ein gutes Buch.
C/C++ für Dummies! Das würde ich jedem empfehlen, der an solch einer 
Aufgabe so verzweifelt ;) Ist nicht bös gemeint damit habe ich auch 
angefangen vor ca. 10 Jahren! ;)

Die einfachste Lösung ist echt wie Rolf Magnus schreibt:

float tmpBuffer;
char* buffer = (char*)&tmpBuffer;

Oder

float f = 5.5f;
char buf[4];
memcpy(buf,&f,sizeof(f);


Ich verstehe grad nicht weshalb das jetzt noch weiter diskutiert werden 
muss. Man muss nicht immer das Rad neu erfinden.

P.S. die Rückumwandlung von char[4] in float sieht dann so aus:
memcpy (&f, buf, sizeof(buf));

von Uhu U. (uhu)


Lesenswert?

Cnewbie wrote:
> Du bist echt so ein Großkotz Uhu Uhuhu!

Das scheint dein eigentliches Problem zu sein: Kein Sitzfleisch, dir 
Dinge anzueignen, die etwas komplexer sind, als ein Laib Brot.

Es ist noch kein Software-Ingenieur vom Himmel gefallen. Von Geburt aus 
nicht programmieren zu können ist keine Schande.

Peinlich wirds allerdings, wenn man meint, irgendwo mittendrin 
einsteigen zu können, ohne die Grundbegriffe zu kennen.

Also: Lerne erstmal was, dann helfen wir dir hier gerne weiter. Auf dem 
Niveau von Putzfrauenwissen über Programmierung macht das keinen Spaß 
und bringt dir letztlich auch nicht viel.

Einen recht ordentlichen Eindruck macht übrigens das C-Tutorial bei 
http://www.roboternetz.de/wissen/index.php/C-Tutorial

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.