Zeiger auf Char zeigt auf Float

Der chaotische Hauptfaden

Moderatoren: Heaterman, Finger, Sven, TDI, Marsupilami72, duese

Antworten
Benutzeravatar
Finger
Administrator
Beiträge: 7392
Registriert: Di 12. Jun 2012, 20:16
Kontaktdaten:

Zeiger auf Char zeigt auf Float

Beitrag von Finger »

Moin Jungs,

ich stehe gerade total auf dem Schlauch. Ich bin auf einer 8Bit-Maschine unterwegs:

Code: Alles auswählen

char * KalibrierZeigerEEP;
float Kalibrierpunkt;

KalibrierZeigerEEP = &Kalibrierpunkt;				
Das erzeugt logischerweise ne Warnung (Zeiger auf Char zeigt auf Float). Ich müsste die also durch einen geeigneten typecast loswerden. Aber wie?
Ich brauche einen Zeiger auf das erste Byte im Speicher des Floats. Ich würde das ja mit dem UNION lösen, aber das geht doch eleganter, oder?

Ciao,

Finger
Benutzeravatar
Fritzler
Beiträge: 12579
Registriert: So 11. Aug 2013, 19:42
Wohnort: D:/Berlin/Adlershof/Technologiepark
Kontaktdaten:

Re: Zeiger auf Char zeigt auf Float

Beitrag von Fritzler »

Arrays?

Also machst wiedern Zeiger auf dne Float und machst dann nen Zeiger auf das erste Element des Speicherberichs.

Mal gucken obs hinhaut:

Code: Alles auswählen

float floating;
void *zeiger;
char byte;

zeiger = (void*)&floating;
zeiger = &zeiger[0];
byte = (char)*zeiger;

Ansolnsten eben Union, wie eigentlich immer :mrgreen:
Benutzeravatar
omega
Beiträge: 520
Registriert: So 11. Aug 2013, 14:36
Kontaktdaten:

Re: Zeiger auf Char zeigt auf Float

Beitrag von omega »

Das sollte doch so gehen:

Code: Alles auswählen

char * KalibrierZeigerEEP;
float Kalibrierpunkt;

KalibrierZeigerEEP = (char *) &Kalibrierpunkt; 
Benutzeravatar
Finger
Administrator
Beiträge: 7392
Registriert: Di 12. Jun 2012, 20:16
Kontaktdaten:

Re: Zeiger auf Char zeigt auf Float

Beitrag von Finger »

HA! Das wars was ich suchte *Kopf -> Tisch* Ich danke euch.
Benutzeravatar
Kuddel
Beiträge: 5074
Registriert: Fr 28. Jun 2013, 10:56
Wohnort: Denk immer an St. Alamo!

Re: Zeiger auf Char zeigt auf Float

Beitrag von Kuddel »

Das kommt aber nicht aus QT, oder?
Gruß
Kuddel
Benutzeravatar
Sven
Beiträge: 4421
Registriert: Fr 28. Jun 2013, 12:52
Wohnort: Sechsundzwanzigdreisechzehn

Re: Zeiger auf Char zeigt auf Float

Beitrag von Sven »

Unter C++ (also auch wenn man die QT Lib benutzt) würde man korrekterweise schreiben:

Code: Alles auswählen

static_cast<char*>( &Kalibrierpunkt); 
Der typische C Cast ist zwar schneller zu schreiben aber es gilt als guter Programmierstil, explizit statische Casts in C++ zu verwenden.
Es gibt schließlich auch noch den reinterpret-Cast, const-Cast und den dynamischen Cast.

Das fällt besser ins Auge als der einfache C-Cast. Das kann oftmals vorteilhaft für das Codeverständnis sein. Außerdem meckert der Compiler bei C-Casts
nicht, wenn man sich an "unsinnigen" Casts versucht. Zum Beispiel Int-Pointer zu size_t. (Wenn man die Speicheradresse ausgeben will).

Außerdem lässt sich in C++ der Cast Operator von Klassen überladen. Man könnte quasi eine Euro-Klasse schreiben und dort einen Cast-Operator
für Britische Pfund implementieren. Dann kann man einen static_cast<BritischePfund>( EuroObjekt) aufrufen.
Man muss keinen expliziten Cast-Operator definieren, wenn ein Konstruktor mit nur einem Argument des Quell-Typs existiert.
In diesem Beispiel wäre das ein Konstruktor für die Britische Pfund Klasse, die als Argument gerne eine Variable des Typs Euro hätte.
Man kann weiterhin gezielt überladen, wenn man irgendwelche "abgefahrenen" Dinge implementieren will. Mir fällt aber grad kein Beispiel ein, warum ein überladener Cast Operator und ein Single-Argument Konstruktor parallel existieren müssten.
Benutzeravatar
ferdimh
Beiträge: 9379
Registriert: Fr 16. Aug 2013, 15:19

Re: Zeiger auf Char zeigt auf Float

Beitrag von ferdimh »

Ist der gewollte cast aber nicht der reinterpret_cast?
Benutzeravatar
Sven
Beiträge: 4421
Registriert: Fr 28. Jun 2013, 12:52
Wohnort: Sechsundzwanzigdreisechzehn

Re: Zeiger auf Char zeigt auf Float

Beitrag von Sven »

Nein, der gewollte cast ist ein Static Cast.
Der reinterpret Cast interpretiert quasi die ganzen Bits des Quellobjekts neu. Der Static Cast konvertiert statisch.

Mit dem Reinterpret Cast kann man sich quasi anschauen, welcher Ganzzahl das Bitmuster einer Float Zahl entspricht.
Benutzeravatar
ferdimh
Beiträge: 9379
Registriert: Fr 16. Aug 2013, 15:19

Re: Zeiger auf Char zeigt auf Float

Beitrag von ferdimh »

Mit dem Reinterpret Cast kann man sich quasi anschauen, welcher Ganzzahl das Bitmuster einer Float Zahl entspricht.
... Und so wie ich Finger verstehe, ist genau das, was er will - im Übrigen auch das Gleiche, was ne Union tut.
Benutzeravatar
Sven
Beiträge: 4421
Registriert: Fr 28. Jun 2013, 12:52
Wohnort: Sechsundzwanzigdreisechzehn

Re: Zeiger auf Char zeigt auf Float

Beitrag von Sven »

Jetzt habe ich es auch gelesen ;)

Im Zweifelsfall geht auch immer der Weg über einen Void-Pointer.
Benutzeravatar
xoexlepox
Beiträge: 4814
Registriert: So 11. Aug 2013, 19:28
Wohnort: So etwa in der Mitte

Re: Zeiger auf Char zeigt auf Float

Beitrag von xoexlepox »

Willst du etwa das "floating point Format" der Kiste auseinanderdröseln? Für diesen Zweck würde ich eher einen "unsigned char *" empfehlen ;)

@Sven: Jaaa, das ist eigentlich das "richtige" Verfahren (verwende auch ich gerne, obwohl es oft in die Kategorie "übler Hack" eingeordnet wird), jedoch bei einem "pointer++" kann das auch böse in die Hose gehen (-> was ist "++" bei einem "void *"?) ;)
Benutzeravatar
Finger
Administrator
Beiträge: 7392
Registriert: Di 12. Jun 2012, 20:16
Kontaktdaten:

Re: Zeiger auf Char zeigt auf Float

Beitrag von Finger »

Ne, das Format ist wurscht. Aber ich muss es byteweise in ein EEprom stecken :-)
Benutzeravatar
ferdimh
Beiträge: 9379
Registriert: Fr 16. Aug 2013, 15:19

Re: Zeiger auf Char zeigt auf Float

Beitrag von ferdimh »

Ist es nicht...
Ein static_cast würde Informationsverlust bedeuten. Denn dann würde alles auf -128 bis +127 in 1er schritten abgebildet...
Hier ist ein reinterpret_cast richtig (oder der void * pointer, der ist mein Liebling)
Noch besser: Alle Daten in ne struct packen und die als ganze über void * pointer ins EEPROM knallen (bei der gelegenheit kommt ne Prüfsumme auch noch gut).
Benutzeravatar
xoexlepox
Beiträge: 4814
Registriert: So 11. Aug 2013, 19:28
Wohnort: So etwa in der Mitte

Re: Zeiger auf Char zeigt auf Float

Beitrag von xoexlepox »

ferdimh hat geschrieben:Ein static_cast würde Informationsverlust bedeuten. Denn dann würde alles auf -128 bis +127 in 1er schritten abgebildet...
Warum? M.E. wird der Bereich von -128 bis +127 (incl. 0), den ein einzelnes Byte enthalten kann, doch exakt davon abdeckt? Und dann geht's weiter bei dem nächsten Byte... Klar, dabei must du (besser: Das Programm) wissen, wieviele Bytes ein "float" beinhaltet, aber das "herauszubekommen" sollte nicht schwer sein ;)

Sorry, wenn meine Kenntnisse "ein wenig veraltet" sind, aber "stl" ist nicht so ganz mein Gebiet und die unterschiedlichen cast-Moglichkeiten sagen mir nicht so sonderlich viel, aber die Idee mit der Prüfsumme gefällt mir.

Edit: Ist vielleicht der "static_cast" eine Umformung "des Ganzen" auf den Zieltyp, also anders als der "klassische Cast", der nichts an den Daten ändert, auf die er zeigt?
Benutzeravatar
Fritzler
Beiträge: 12579
Registriert: So 11. Aug 2013, 19:42
Wohnort: D:/Berlin/Adlershof/Technologiepark
Kontaktdaten:

Re: Zeiger auf Char zeigt auf Float

Beitrag von Fritzler »

Finger hat geschrieben:Ne, das Format ist wurscht. Aber ich muss es byteweise in ein EEprom stecken :-)
Na dann sach det doch gleich!

Guggste hier:

Code: Alles auswählen

float floating;
float *zeiger;

//EEPROM schreiben
zeiger = &floating;
i2c_write((char)zeiger[0]);
i2c_write((char)zeiger[1]);
i2c_write((char)zeiger[2]);
i2c_write((char)zeiger[3]);

//EEPROM lesen
zeiger = &floating;
zeiger[0] = i2c_read();
zeiger[1] = i2c_read();
zeiger[2] = i2c_read();
zeiger[3] = i2c_read();
Ansonsten eben Union (funktionen aus einer RTC IC Lib von mir mit etwas RAM am Ende):

Code: Alles auswählen

void PCFRAM_write_float(uint8_t adress, float zahl) {
	union {
		float zahl;
		uint32_t bits;
	} float_to_raw;
	float_to_raw.zahl = zahl;
	PCFRAM_write_dword(adress, float_to_raw.bits);
}

float PCFRAM_read_float(uint8_t adress) {
	union {
		float zahl;
		uint32_t bits;
	} raw_to_float;
	raw_to_float.bits = PCFRAM_read_dword(adress);
	return raw_to_float.zahl;
}
Benutzeravatar
ferdimh
Beiträge: 9379
Registriert: Fr 16. Aug 2013, 15:19

Re: Zeiger auf Char zeigt auf Float

Beitrag von ferdimh »

Edit: Ist vielleicht der "static_cast" eine Umformung "des Ganzen" auf den Zieltyp, also anders als der "klassische Cast", der nichts an den Daten ändert, auf die er zeigt?
Genau das ist der Fall.
static_cast versucht den "Inhalt" so gut wie möglich beizubehalten
dynamic_cast auch, aber da müssen die typen zur Compilezeit nicht bekannt sein.
reinterpret_cast behält das Bitmuster bei (Es wird "neu interpretiert").
Benutzeravatar
xoexlepox
Beiträge: 4814
Registriert: So 11. Aug 2013, 19:28
Wohnort: So etwa in der Mitte

Re: Zeiger auf Char zeigt auf Float

Beitrag von xoexlepox »

ferdimh hat geschrieben:static_cast versucht den "Inhalt" so gut wie möglich beizubehalten
Danke, wieder was dazu gelernt... Dieses Forum ist eben (selbst noch für "alte C-Knochen") lehrreich :D
Benutzeravatar
Sven
Beiträge: 4421
Registriert: Fr 28. Jun 2013, 12:52
Wohnort: Sechsundzwanzigdreisechzehn

Re: Zeiger auf Char zeigt auf Float

Beitrag von Sven »

Genau, der static_cast Befehl ruft den entsprechenden Konstruktor der Zielklasse auf oder wenn vorhanden den speziellen Cast Operator.
Wenn man sich eine Klasse für römische Zahlen schreibt, würde es genügen, einen Konstruktor zu haben, der nur einen int als Argument hat, um von int zu römische Zahl
casten zu können.

Gibt es keinen entsprechenden Einzelargument Konstruktor und einen entsprechenden überladenen Cast Operator, wird sich der Compiler beschweren.
Bei einem dynamic_cast muss man zur Laufzeit des Programms den Fehler abfangen.

Auf Void Pointer ist keine Pointer-Arithmetik zugelassen! (Zumindest nicht bei standardkonformen C/C++).
Der Typ eines Pointers verrät dem Compuer schließlich erst, wieviel Speicher das Element dahinter einnimmt, der Pointer selber ist nur eine Speicheradresse.
Die könnte man prinzipiell auch in einer size_t Variable speichern oder irgendwelchen anderen Variablen, die lang genug sind. Unter C++ würde man dafür dann den reinterpret_cast benutzen ;)

Void Pointer sollte man quasi nur für generische Schnittstellen verwenden, bei denen man den Datentyp nicht festlegen möchte, z.B. bei Threading mit PThreads.
Ein Void Pointer sollte immer zum gewünschten Datentyp umgecastet werden. Das birgt gewisse Gefahren, wenn jemand einen falschen Datentyp übergibt.
Daher sollte bei Funktionen, die Void-Pointer umcasten sichergestellt sein, dass nur richtige Datentypen übergeben werden können.
Also niemals eine Schnittstelle definieren, die Void-Pointer akzeptiert und dann intern umcastet.

@Fritzler:
Musst du beim lesen nicht den Float-Pointer auf Char-Pointer umcasten? Sonst versucht doch der Index-Operator auf ein Float-Array zuzugreifen und nicht auf ein Char-Array.
Benutzeravatar
Fritzler
Beiträge: 12579
Registriert: So 11. Aug 2013, 19:42
Wohnort: D:/Berlin/Adlershof/Technologiepark
Kontaktdaten:

Re: Zeiger auf Char zeigt auf Float

Beitrag von Fritzler »

Sven hat geschrieben: @Fritzler:
Musst du beim lesen nicht den Float-Pointer auf Char-Pointer umcasten? Sonst versucht doch der Index-Operator auf ein Float-Array zuzugreifen und nicht auf ein Char-Array.
Ups!
Ja so sollte es auch sein.
Ging beim Kopierpasten wohl irgendwie unter :?
Antworten