Forum: Compiler & IDEs wieder mal die pointer.


von fugitivus (Gast)


Lesenswert?

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 ?!?!

von tobi (Gast)


Lesenswert?

Wenn du aus einem Float 4 Bytes machen willst, dann ist dies über eine 
Union deutlich leichter.
1
typedef union {
2
    float f_val;
3
    uint32_t i_val;
4
} ftou;
oder
1
typedef union {
2
    float f_val;
3
    uint8_t bytes[4];
4
}

Deine Variante könnte, soweit ich das sehe, auch funktionieren, falls 
der Cast vor dem + ausgewertet wird.

von Oliver (Gast)


Lesenswert?

Zuammenbauen ginge etwa so:
1
float btof(uint8_t b0, uint8_t b1,uint8_t b1,uint8_t b3)
2
{
3
    float f;
4
    uint8_t *ptr;
5
    
6
    ptr = (uint8_t*) &f;
7
8
    *ptr++ = b0;
9
    *ptr++ = b1;
10
    *ptr++ = b2;
11
    *ptr = b3;
12
13
    return f;
14
}

Aber mit einer union geht das alles viel einfacher:
1
typedef union
2
{
3
   uint8_t bytes[4];
4
   float floatval;
5
} bytefloat;
6
7
bytefloat wert;
8
9
wert.floatval = 3.41;
10
uint8_t b0 = wert.bytes[0];

Oliver

von Karl H. (kbuchegg)


Lesenswert?

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.
1
void btof(float * input , uint8_t index, uint8_t byte)
2
{
3
   uint8_t * ptr;
4
   ptr = (uint8_t *)input + index;
5
   *ptr = byte;
6
}

von fugitivus (Gast)


Lesenswert?

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...

von fugitivus (Gast)


Lesenswert?

hehe ich habe den poiter falsch erhöht....

problem gelöst... danke !!

von Karl H. (kbuchegg)


Lesenswert?

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!

von fugitivus (Gast)


Lesenswert?

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 !!

von tobi (Gast)


Lesenswert?

Codeschnipsel?

von fugitivus (Gast)


Lesenswert?

oehm in wie fern ?!? steht doch quasi alles oben xD

von tobi (Gast)


Lesenswert?

fugitivus schrieb:
> oehm in wie fern ?!? steht doch quasi alles oben xD

Wo denn? Zeig dochmal was genau du geamcht hast.

von Karl H. (kbuchegg)


Lesenswert?

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.

von Oliver (Gast)


Lesenswert?


von fugitivus (Gast)


Lesenswert?

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)

von fugitivus (Gast)


Lesenswert?

oh mein gott... schreiben lernen.... xD

von Karl H. (kbuchegg)


Lesenswert?

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.

von fugitivus (Gast)


Lesenswert?

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 !

von Karl H. (kbuchegg)


Lesenswert?

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

von Peter (Gast)


Lesenswert?

> for(i=0;i<3;i++)
> {
>     bytes[i] = ftob(floatval,i);
> }
sollte doch auch einfacher gehen
1
memcpy( bytes, &floatval, sizeof( floatval ) );

von Karl H. (kbuchegg)


Lesenswert?

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.

von Karl H. (kbuchegg)


Angehängte Dateien:

Lesenswert?

Edit: Bild vergessen

von fugitivus (Gast)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

fugitivus schrieb:

> vor nem halben jahr hab ich noch in basic geproggt xD

Der Herr steh uns bei :-)

von tobi (Gast)


Lesenswert?

In deiner Schleife müsste es <4 heisen und nicht <3. Warum machst du dir 
überhaupt die Mühe mit fehleranfälligen Pointern?
1
#include <avr/io.h>
2
#include <inttypes.h>
3
4
typedef union {
5
  float f_val;
6
  uint8_t bytes[4];
7
} float_bytes_t;
8
9
int main(void)
10
{
11
  float_bytes_t foo;
12
13
  foo.f_val = 1.0f;
14
15
  PORTA = foo.bytes[3];
16
  PORTB = foo.bytes[2];
17
  PORTC = foo.bytes[1];
18
  PORTD = foo.bytes[0];
19
20
  while(1) {
21
    asm volatile("nop");
22
  }
23
}

Ergebnis:

PORTA = 0x3F
PORTB = 0x80
PORTC = 0x00
PORTD = 0x00

von Martin (Gast)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von Rolf Magnus (Gast)


Lesenswert?

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.

von fugitivus (Gast)


Lesenswert?

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....

von Oliver (Gast)


Lesenswert?

>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

von Karl H. (kbuchegg)


Lesenswert?

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.

von fugitivus (Gast)


Lesenswert?

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....

von Oliver (Gast)


Lesenswert?

>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

von fugitivus (Gast)


Lesenswert?

>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 ?!?!

von fugitivus (Gast)


Lesenswert?

ich meine, du postest mich voll mit union und so, gehst aber überhaupt 
nicht auf meine frage ein....

von Karl H. (kbuchegg)


Lesenswert?

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)

von Mano W. (Firma: ---) (manow)


Lesenswert?

Wenn Du HIlfe möchtest, dann musst Du auch brauchbares posten und nicht 
nur irgendwelche Ausschnitte...

von Werner B. (werner-b)


Lesenswert?


von wolfgang (Gast)


Lesenswert?

qed
aus Donald E. Knuth 'The art of computer programming' 1967

"Pointers are a step backwards from witch we will never recover"

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.