Hallo, in einem Projekt will ich verschiedenartige Datentypen in einem EEPROM via SPI abspeichern. Dazu sende ich nacheinander z.B die vier Bytes eines double-Wertes zum SPDR Register. So sieht das dann aus: double double_var=1123.6; uint8_t *ptr_double_var; ptr_double_var=&double_var; SPDR=*ptr_double_var; ptr_double_var++; SPDR=*ptr_double_var; ptr_double_var++; SPDR=*ptr_double_var; ptr_double_var++; SPDR=*ptr_double_var; Das ganze funktioniert auch problemlos. Allerdings kommt beim komplieren die Warnmeldung "Assignment from incompatible pointer type". Sollte ich den Zeiger anders initialisieren ?
Seby schrieb: > double double_var=1123.6; > uint8_t *ptr_double_var; > ptr_double_var=&double_var; Seby schrieb: > "Assignment from incompatible pointer type". Du könntest ptr_double_var als voidpointer (bäääh) initalisieren, dann sollte die Warnung verschwinden. BTW: Doubles haben 64bit, du musst also 8 Bytes rausschieben.
Nee, aber in den Zielpointer casten. ptr_double_var = (uint8_t *) &double_var; Mit AVR-GCC ist double und float in der Größe gleich und 4 Bytes groß. Es ist "Zufall", dass dein Programm funktioniert.
@ Stefan Kein Zufall. Ich habe (da ich mir nicht sicher war) die Größe eines doublewertes mit dem sizeof-Operator ermittelt (4 Bytes)
Hi,
1 | double double_var=1123.6; |
2 | uint8_t *ptr_double_var; |
schau dir mal deine var an! Typ= double !!! und dein Pointer -> ..... !!!! genau: Assignment from incompatible pointer type mach es mit maskierungen ist meiner bescheidenen Meinung nach sicherer! Angenommen dein DOUBLE ist 4 Byte lang:
1 | char bytes[4]; |
2 | for( a= 0; a < 4; a++) |
3 | {
|
4 | bytes[a]= double_var & (0xff <<( a*8)); |
5 | }
|
ist schon spät, ich hoffe es ist richtig..... Stephan
Ich gebe zu dass ich noch nicht so lange programmiere. Aber so wie ich es programmiert habe läuft es halt viel schneller ab. Bei deiner Variante dauerts duch die Schieberei doch viel länger, oder ? Ehrlich gesagt hab ich mich von der Funktions memcpy(...) inspirieren lassen. Da werden doch auch nur Bytes von einer Stelle im RAM bzw. Registen woanders hinkopiert.
ja, aber gut kannst die Schleife auch auf bröseln und mit const Werten maskiern. Das Problem ist das double nicht gleich double ist. >Stefan: >Mit AVR-GCC ist double und float in der Größe gleich und 4 Bytes groß. >Es ist "Zufall", dass dein Programm funktioniert. die andere Vorredner haben schon recht! Du könntest das auch mit einer Union lösen:
1 | union{ |
2 | double dvar; |
3 | char bytes[sizeof(double)] |
4 | };
|
Da kannst du dann auch direkt auf die Bytes zugreifen. Sind halt nur irgendwie Vorschläge die wir hier machen, du musst die nicht übernehmen. Caste deinen Pointer bei der Zuweisung und dein Compiler ist glücklich. :-) Stephan
Ok, ich sollte mich erstmal mit Unions befassen. Habe bisher nur mit structs gearbeitet... Dann verstehe ich vielleicht auch deinen Code (-;
hier gefunden: http://home.fhtw-berlin.de/~junghans/cref/SYNTAX/union.html
1 | Mit dem Schluesselwort union legt man fest, |
2 | dass sich mehrere Variablen verschiedenen Datentyps den gleichen Speicherplatz teilen. |
Stephan
Auf dem gleichen Speicherplatz ? Sind sie etwa hintereinander im RAM abgespeichert ?
Ok ich hab´s kapiert. union{ double dvar; char bytes[sizeof(double)] }; Bei einem Struct wären die variablen unabhängig voneinander. Wenn ich der Variable dvar einen Wert zuweise würde das Array nicht geändert werden bzw. umgekehrt. In diesem Fall jedoch belegt das union 4 Bytes und die Variablen decken sich sozusagen. Richtig ?
Stephan W. schrieb: > Du könntest das auch mit einer Union lösen:union{ > double dvar; > char bytes[sizeof(double)] > }; > Da kannst du dann auch direkt auf die Bytes zugreifen. Ist halt undefined behaviour.
Mario schrieb: > Stephan W. schrieb: >> Du könntest das auch mit einer Union lösen:union{ >> double dvar; >> char bytes[sizeof(double)] >> }; >> Da kannst du dann auch direkt auf die Bytes zugreifen. > > Ist halt undefined behaviour. Was hab ich vergessen?
Nichts. So eine Konvertierung ist prinzipiell nicht portabel, gleich ob man vercastete Zeiger nimmt, oder union oder sonstwas nimmt. Insofern muß man sich nur dieser Tatsache bewusst sein und das Konstrukt (welches auch immer) nicht unbesehen in einer anderen Umgebung verwenden.
Stephan W. schrieb: > Mario schrieb: >> Stephan W. schrieb: >>> Du könntest das auch mit einer Union lösen:union{ >>> double dvar; >>> char bytes[sizeof(double)] >>> }; >>> Da kannst du dann auch direkt auf die Bytes zugreifen. >> >> Ist halt undefined behaviour. > > Was hab ich vergessen? Dass der C-Standard vorschreibt, dass man aus einer Union nur den Typ zuverlässig lesen kann, den man auch als letztes beschrieben hat. Alles andere führt zu "undefined behaviour".
1 | u.dvar = 1.0; |
2 | byte = u.bytes[0]; |
Ein Compiler könnte z.B. zur Optimierung einfach die zweite Zeile durch "x = 0;" ersetzen, und wäre trotzdem Standard konform. Da aber Unions alle Nase lang für solche Typ-Umwandlungen "misbraucht" werden, wird das vermutlich kein Compiler je wagen. ;-)
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.