mikrocontroller.net

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


Autor: Cnewbie (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Christian R. (supachris)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Cnewbie (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Cnewbie (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
1 Byte sind 8 Bit

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

Autor: Cnewbie (Gast)
Datum:

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

Autor: Cnewbie (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo..........

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was hast du denn ausprobiert?

Autor: Cnewbie (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Cnewbie (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gibt es schon dafür Funktionen?

Autor: Balu (Gast)
Datum:

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

Autor: Jorge (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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));


}

Autor: Cnewbie (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Rolf Magnus (Gast)
Datum:

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

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Cnewbie wrote:
> Dies müsste doch so gehen oder?

Garantiert nicht.

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Cnewbie (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Cnewbie (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Cnewbie (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also ich finde, es wird darum so ein großes Geheimnis gemacht.

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Also diese Diskussion hat mir nicht sonderlich viel geholfen

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

Das wäre ohne Kopieren. Wenn du die Bytes kopieren willst:
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.

Autor: Cnewbie (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So meinst du das?
unsigned char array[10];

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

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

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

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?
memcpy(buf,f,sizeof(f);

Autor: Cnewbie (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So meinst du das?
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[3-i] =charPtr;
   }
}

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

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?
memcpy(buf,f,sizeof(f);

Autor: Cnewbie (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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
unsigned char buf[4];
float f;
f=12.3456;

memcpy(buf,f,sizeof(f));
printf("buf[0]: %c, buf[1]: %c, buf[2]: %c, buf[3]:  %c\n",buf[0],buf[1],buf[2],buf[3]);

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> So meinst du das?

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

oder gar
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:
memcpy(buf, &fvalue, sizeof fvalue);

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Cnewbie (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke!

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

Autor: Cnewbie (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Umwandlung von float in 4 Bytes sowie 4 Bytes in float funktioniert.
// convert float to char array
unsigned char buf[4];
float f1=(float)12.3456;
memcpy(buf,&f1,sizeof(f1));

// convert char array to float
float f2;
memcpy(&f2,buf,sizeof(buf));
printf("f2: %lf\n",f2);

Autor: StinkyWinky (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das könnte man doch auch mit einer union machen.

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Cnewbie (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Guile Lampert (sphinx)
Datum:

Bewertung
0 lesenswert
nicht 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));

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht 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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.