Hallo !
Ich habe mal wieder eine frage zu pointern. Mit folgender funktion:
uint8_t ftob(float input , uint8_t index)
{
uint8_t * ptr;
ptr = (uint8_t *)&input + index;
return *ptr;
}
will ich aus einem float 4 bytes machen.... (scheint auch zu klappen).
Ich kann aber nicht wirklich überprüfen ob es klappt weil ich es nicht
hinbekomme das float wieder zusammen zu bekommen.
Meine Fragen :
1.Ist mein Beispiel so richtig ?!? oder hab ich schon wieder n Brett
vorm Kopf ?!?
2.Wie müsste ich beim zusammenbauen vorgehen ?!?!
fugitivus schrieb:
> Hallo !>> Ich habe mal wieder eine frage zu pointern. Mit folgender funktion:>> uint8_t ftob(float input , uint8_t index)> {> uint8_t * ptr;> ptr = (uint8_t *)&input + index;> return *ptr;> }>> will ich aus einem float 4 bytes machen....
Du willst auf das index-ste Byte eines float zugreifen. Richtig?
> Meine Fragen :> 1.Ist mein Beispiel so richtig ?!? oder hab ich schon wieder n Brett> vorm Kopf ?!?
Wenn die Aufgabenstellung die ist, die ich vermute: Ja kann man so
machen
> 2.Wie müsste ich beim zusammenbauen vorgehen ?!?!
Genau umgekehrt? Anstelle das Byte von der Adresse zu lesen, wird das
Byte dorthin geschrieben. Dabei musst du aber beachten, dass für input
keine Kopie innerhalb der Funktion angelegt wird, sondern dass du
tatsächlich die Adresse der aufrufenden float Variablen benutzt um dort
das Byte abzulegen.
Herzlichen dank für die vielen antworten !!!!
Ich werd gleich mal gucken wie ich das am besten mache...
union kannte ich noch garnet.... aber das gefällt mir scheinbar gut :-)
und das mit dem genau umgekehrt schreiben habe ich versucht ging
nicht... aber ich gucke noch mal wer weis was ich da scho wieder falsch
gemacht habe...
fugitivus schrieb:
> Herzlichen dank für die vielen antworten !!!!>> Ich werd gleich mal gucken wie ich das am besten mache...> union kannte ich noch garnet.... aber das gefällt mir scheinbar gut :-)
Du brauchst ein C Buch!
Hi nochmal.....
hehe ja das mit dem buch stimmt....
ich hab da noch ne frage vlt weis auch jemand wie ich die oben genannten
sachen mit avr-gcc nutzen kann ?!?!
Ich binn mir bewust darüber das datentypen je nach plattform
unterschiedlich seien können..... aber was mir der mc rausschmeist
scheint absoluter quatsch zu sein....
bsp:
00000000 00000000 10000000 10000000 --> 1
00000000 00000000 10100000 10000000 --> 2
00000000 00000000 11000000 10000000 --> 3
00000000 00000000 11100000 10000000 --> 4
00000000 00000000 00000000 10000000 --> 5
das ist für mich die reinste bizarrowelt........
hätte mit allem gerechnet aber nicht damit....
deswegen kann das meiner ansicht nach nur nen fehler sein
und nicht der unterschied zwischen dem float im avr und dem aufm i386
kann mir irgendjemand etwas nützliches dazu sagen ?!?
Herzlichen Dank !!
fugitivus schrieb:
> oehm in wie fern ?!? steht doch quasi alles oben xD
Nö.
Das sind nur ein paar nichtssagende Schnipsel, in denen eigentlich gar
nichts passiert, ausser einem Pointer einen anderen Datentyp
unterzujubeln, damit sich der Compiler beim Zugriff auf die Bytes
raushält.
Aber wie sieht der Rest aus? Wie werden die Schnipsel verwendet? Du bist
nicht der erste, der sich über seltsame Ergebnisse wundert und hinterher
stellt sich raus, dass alle seine Berechnungen richtig sind und nur die
Ausgabe der Ergebnisse fehlerhaft war.
uint8_t ftob(float input , uint8_t index)
{
uint8_t * ptr;
ptr = (uint8_t *)&input + index;
return *ptr;
}
for(i=0;i<3;i++)
{
bytes[i] = ftob(floatval,i);
}
und dann den scheiss seriell versendet..... u. auf display ausgegeben
(nicht das du jezt dengst ich hätte n fehler beim senden)
fugitivus schrieb:
> uint8_t ftob(float input , uint8_t index)> {> uint8_t * ptr;> ptr = (uint8_t *)&input + index;> return *ptr;> }>>> for(i=0;i<3;i++)> {> bytes[i] = ftob(floatval,i);> }>> und dann den scheiss seriell versendet..... u. auf display ausgegeben
Zieh jetzt gleich deine Asbest-Unterwäsche an. Denn gleich wirds
losgehen :-)
> (nicht das du jezt dengst ich hätte n fehler beim senden)
Wenn ich Fehler suche, die ich nicht erklären kann, dann gehe ich
grundsätzlich davon aus, dass der Fehler überall stecken kann.
Inclusive: ich geh mit den falschen Werten in den Algorithmus rein.
Nichts wird als gesichert angenommen, es sei denn es wurde bereits
konkret im Zusammenhang mit diesem Fehler überprüft. Das Minimum ist
(auf dem PC): Im Debugger einmal durchsteppen und Stichproben bei den
Variablen nehmen. Wenn dabei auch nur das Geringste auffällt, wird die
Funktion auseinandergenommen und mit der Lupe abgesucht. Egal wie
angeblich fehlerfrei die Funktion sein müsste.
gut... aber der fehler kann nur hier stecken denn der rest den ich sende
ist überall 100 % in ordnung.....nur das umwandeln funktioniert
nicht..... da binn ich mir sicher..... kann dir aber jezt nicht wirklich
n 3000 zeilen code hier ins forum stellen, damit du dich davon
überzeugen kannst.... ich werde mal weiter gucken ob ich raus finde
woran es liegt....
werde dann posten worann es gelegen hatt (nutfalls werde ich einfach n
string draus machen und den seriell senden findsch zwar nicht so schön,
aber wird sich dann zeigen....
trozdem erst mal danke !
fugitivus schrieb:
> gut... aber der fehler kann nur hier stecken denn der rest den ich sende> ist überall 100 % in ordnung
Den maximalen Rekord, den ich je hatte, war eine Funktion die seit über
10 Jahren im Produktionscode im Einsatz war und die in Sonderfällen, die
sie eigentlich beherrschen sollte, versagte.
> .....nur das umwandeln funktioniert> nicht.....
Du hast es immer noch nicht geschnallt.
Da wird überhaupt nichts umgewandelt.
Der Compiler wird nur hineingetrickst, zu vergessen, dass an dieser
Stelle im Speicher ein float steht und dass der Zugriff direkt auf das
Byte im Speicher erfolgt ohne das der Compiler dieses Byte und die
nachfolgenden als float auffasst. Es ist, wie wenn du über eine
Buchseite ein Blatt Papier mit einem Guckloch legst und im Guckloch nur
1 Buchstabe sichtbar ist.
Nichts wird gewandelt, nichts wird umgerechnet
Die korrekten Zahlen auf einem AVR wären
1 0x00 0x00 0x80 0x3F
2 0x00 0x00 0x00 0x40
3 0x00 0x00 0x40 0x40
4 0x00 0x00 0x80 0x40
5 0x00 0x00 0xA0 0x40
6 0x00 0x00 0xC0 0x40
7 0x00 0x00 0xE0 0x40
8 0x00 0x00 0x00 0x41
Bei dir stimmt schon das Exponentenbyte (das letzte) nicht überein.
Schlüssel zur Entzifferung ist das in Wikipedia angegebene Bild der
Bitaufteilung (siehe Anhang)
Bits 31 bis 24 sind im letzten Byte, 23 bis 16 im vorletzten usw.
Die Zahl 5.0, Bytes in derselben Reihenfolge wie auf dem Bild, lautet
hex
0x40 0xA0 0x00 0x00
in Bitdarstellung
0100 0000 1010 0000 0000 0000 0000 0000
laut Wiki zerlegt
Vorzeichen: 0
Exponent: 10000001
Mantisse: 0100000000000000000
Die Mantisse ist 1/4, mit der impliziten 1 vor dem Komma also 1.25
Exponent (nach Abzug des Bias 127): 2
Dieses Bitmuster stellt also die Zahl
1.25 * 2^2 = 1.25 * 4 = 5
dar.
Die Hex-Codes hab ich aus dem Debugger im AVR-Studio.
Verfolg also genaz einfach nur die Bytes für eine der Zahlen durch den
ganzen Weg bis zur Seriellen. Wenn sie dort nicht irgendwo verloren
gehen, dann kontrolliert man zb mit HTerm noch ob sie auf PC Seite noch
korrekt ankommen. Wenn sie das tun, dann gehts weiter im Debugger auf
dem PC bis man bei der Ausgabe angelangt ist.
uff Danke !!!!
damit werd ich glaub ich was anfangen können...
und ja... "umwandeln" war doof ausgedrückt...
habt gedult mit mir xD
vor nem halben jahr hab ich noch in basic geproggt xD
Auch wenn du es zwei Mal wiederholst: In ein Feld einer Union
reinzuschreiben und aus einem anderen auszulesen ist laut C-Standard UB.
Das kann möglicherweise funktionieren, muss es aber nicht - einem
Anfänger das so falsch beizubringen halte ich für keine gute Idee.
Martin schrieb:
> Auch wenn du es zwei Mal wiederholst: In ein Feld einer Union> reinzuschreiben und aus einem anderen auszulesen ist laut C-Standard UB.> Das kann möglicherweise funktionieren, muss es aber nicht - einem> Anfänger das so falsch beizubringen halte ich für keine gute Idee.
:-)
Der springende Punkt ist.
Streng nach C-Standard gibt es keinen 'richtigen' Weg. Auch das Umcasten
des Pointers ist streng genommen 'undefined Behaviour'.
Faktum ist aber auch, dass die union-Methode, genauso wie die Pointer
Methode, auf allen bekannten Compilern funktioniert (Padding Bytes und
Endianess mal aussen vorgelassen) und wohl auch immer funktionieren
wird, obowhl es keine Garantie dafür gibt.
Karl heinz Buchegger schrieb:
> Der springende Punkt ist.> Streng nach C-Standard gibt es keinen 'richtigen' Weg. Auch das Umcasten> des Pointers ist streng genommen 'undefined Behaviour'.
Au contraire! Für jedes beliebige Objekt (außer Bitfeldern) ist
garantiert, daß man es per mepcpy in ein Array aus unsigned char
entspecheder Größe kopiere kann. Bei der Übergabe an memcpy wird der
Zeiger letztendlich auch konvertiert, also muß auch der Cast ok sein.
(Das steht bestimmt auch irgendwo in der ISO-Norm nochmal explizit).
Der Wert, der rauskommt ist "implementation-defined".
> Faktum ist aber auch, dass die union-Methode, genauso wie die Pointer> Methode, auf allen bekannten Compilern funktioniert (Padding Bytes und> Endianess mal aussen vorgelassen) und wohl auch immer funktionieren> wird, obowhl es keine Garantie dafür gibt.
Ich sehe nur nicht, warum es besser sein soll, extra einen neuen
Datentyp anzulegen, eine Variable dieses Typs zu erzeugen, dann den
float-Wert da reinzukopieren und dann den Zielwert wieder
rauszukopieren, wenn ich das gleiche auch mit einem simplen Cast oder
memcpy erreichen kann.
also... jezt mein statement...
also ich binn zwar doof aber scheinbar so doof auch nicht....
der fehler war (ich kann es mir nicht erklähren)
in avr-gcc musste ich den pointer immer einen weiter runter zählen als
in gcc...(warum auch immer)
so...
jezt will ich mal wissen warum, da scheint euer intellekt gefragt zu
sein ;-)
kurz gesagt ich binn froh das ich nicht ganz dolle zu blöd für pointer
binn..
aber dieses rätsel könnte mir ja mal einer entschlüsseln xD
also der fehler war bei den pointern (wie ich es mir gedacht hab....)
aber ich habe viel gelernt durch den post hier, und dafür binn ich sehr
dankbar....
>in avr-gcc musste ich den pointer immer einen weiter runter zählen als>in gcc...(warum auch immer)>so...>jezt will ich mal wissen warum, da scheint euer intellekt gefragt zu>sein ;-)
Solange du keinen aktuellen und lauffähigen Code zeigst, ist das
höchstens eine Frage an die Glaskugel, und die ist dummerweise gerade
etwas kaputt.
Das solche Bytespielereien implementationsabhängig sind, d.h. abhängig
von der Archtektur, auf der sie ausgeführt werden, wurde ja weiter oben
schon gesagt. Was du jetzt mit gcc meinst, solltest du da auch ma näher
erläutern.
Oliver
fugitivus schrieb:
> jezt will ich mal wissen warum, da scheint euer intellekt gefragt zu> sein ;-)
Nö.
Da ist unsere Fähigkeit zu raten gefragt.
Fehler in Code finden, den man nicht sehen kann, erfordert entweder ein
sehr gutes Gedächtnis (wenn man den Code selber geschrieben hat) oder
Hellseherische Fähigkeiten.
hehe da währen wir ja wieder bei dem was oben schon mal gepostet wurde
(von mir xD)
ganz einfach gesagt...
uint8_t ftob(float input , uint8_t index)
{
uint8_t * ptr;
ptr = (uint8_t *)&input + index;
return *ptr;
}
und:
float btof(uint8_t b0, uint8_t b1,uint8_t b1,uint8_t b3)
{
float f;
uint8_t *ptr;
ptr = (uint8_t*) &f;
*ptr++ = b0;
*ptr++ = b1;
*ptr++ = b2;
*ptr = b3;
return f;
}
funktionieren aufm pc wunderbar.....
nur sieht das aufm xmega so aus damit es funktioniert....
uint8_t ftob(float input , uint8_t index)
{
uint8_t * ptr;
ptr = (uint8_t *)&input + index - 1;
return *ptr;
}
und:
float btof(uint8_t b0, uint8_t b1,uint8_t b1,uint8_t b3)
{
float f;
uint8_t *ptr;
ptr = (uint8_t*) &f;
*ptr--;
*ptr++ = b0;
*ptr++ = b1;
*ptr++ = b2;
*ptr = b3;
return f;
}
das mir immer gleich n fehler im rest des codes vorgeworfen wird
,tzetzetze
nein mal ganz im ernst, binn ja dankbar für kritik und vlt sollte ich
auch mal lernen meine posts besser zu gestalten....
aber verstehen muss ich jezt nicht warum ich den pointer aufm mc einen
decreasen muss während ich das auf dem pc nicht muss ?!?
das hatt ja wohl auch nix mit nem unterschied zwischen den datentypen zu
tun oder ?!?
mfg fugittivus....
>nur sieht das aufm xmega so aus damit es funktioniert....
Nee, ne?
Keine Ahnung, was du unter "funktionieren" verstehst, aber sicher nicht
das selbe wie der Rest der Menschheit.
>das mir immer gleich n fehler im rest des codes vorgeworfen wird
Tja, auch wenn es dir nicht gefällt, das hat seinen Grund.
Oliver
>Keine Ahnung, was du unter "funktionieren" verstehst, aber sicher nicht>das selbe wie der Rest der Menschheit.>Tja, auch wenn es dir nicht gefällt, das hat seinen Grund.
sehr hilfreich....
irgendwie kann ich ja mit kritik umgehen... aber hast du auch was
sinnvolles zu sagen ?!?!
fugitivus schrieb:
> float btof(uint8_t b0, uint8_t b1,uint8_t b1,uint8_t b3)
*** ***
> {>>> funktionieren aufm pc wunderbar.....
glaub ich nicht.
Wie hast du das durch den Compiler gekriegt?
> float btof(uint8_t b0, uint8_t b1,uint8_t b1,uint8_t b3)
*** ***
> {> float f;> uint8_t *ptr;>> ptr = (uint8_t*) &f;> *ptr--;>> *ptr++ = b0;
Arrividerci Stack.
Gratulation, du hast soeben Speicher niedergebügelt, in dem du nichts
verloren hast.
> das mir immer gleich n fehler im rest des codes vorgeworfen wird
Weil dein eigentliches Problem dort irgendwo steckt.
eine Schleife die mit falschen Indizes gefüttert wird, eine Abfrage die
falsch ist, ein Array welches Out of Bounds angesprochen wird, ein
String der zu lang wird; irgendwas.
Nochmal: Diese Funktionen (wenn die Trivialfehler korrigiert werden)
sind NICHT dein Problem. Du glaubst nur, dass der Fehler dort irgendwo
steckt.
(Und gaaaaaanz ehrlich: Wenn ich mir so ansehe, welche simplen Fehler du
hier beim posten machst, dann steigt die Wahrscheinlichkeit enorm, dass
im Rest vom Code nach ganz andere Kaliber von Fehler warten)