www.mikrocontroller.net

Forum: PC-Programmierung [C] binäre Darstellung von double -Zahlen


Autor: Herbert Knieling (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo, folgendes Vorhaben habe ich:

Ich habe eine Doublezahl
z.B.

double dWert = 230.43;

Jetzt möchte ich gerne sehen, wie diese im Speicher dargestellt wird.

Leider weiß ich nicht so recht, was die C-Casting Operatoren machen...
Ich schreibe jetzt mal, wie ich es intuitiv machen würde und freue mich 
auf eure Korrekturen:


Folgende Programmzeilen sollen
1. einen Pointer auf den Anfang der Zahl darstellen.
da ich byteweise den Speicher auslesen möchte, halte ich unsigned char 
für sinnvoll.
2. Zählvariable deklarieren, da ich ja nacheinander alle Bytes der 
Doublezahl durchwandern möchte.
3. Jetzt weise ich meinem Pointer die Adresse der Double zu.
Hierzu caste ich zuerst auf ein void*, dass keine komischen Umrechnungen 
und Rundungen durchgeführt werden (wie gesagt: ich weiß leider nicht, 
was die Casting operatoren machen)
Dann caste ich auf unsigned char*, da ich ja eine unsigned char Pointer 
Variable habe.
4. Double Zahl = 64 Bit = 8 Byte-> schleife über i = 0..7
5. Gib Speicher an Adresse hexadezimal aus und erhöhe diese Adresse 
insgesamt 8 mal...


Könnte ich das irgendwie so machen, oder ist das ganz falsch?

unsigned char * pU; // Pointer auf den Anfang der  Zahl
int i;
pU =  (unsigned char *)  ((void*) &dWert);

for (i = 0; i < 8; i++)
{
   printf( "%x ", *(pU ++));

}

Vielen Dank für Korrekturen...

Autor: Florian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
http://de.wikipedia.org/wiki/IEEE_754

Du könntest auch
pU = ( unsigned char *) &dWert;

verwenden.

Diese Casting-Operation macht aus einem *double ein *unsigned char, so 
dass *pU ein unsigned char liefert und bei pU++ (in den meisten Fällen) 
die Adresse um 1 erhöht wird.

Würdest Du
double *pD = &dWert;
machen, dann würde *pD einen Double liefern und bei pD++ die Adresse (in 
den meisten Fällen) um 8 erhöht werden.

Du könntest auch
union {
    double d;
    unsigned char u[8];
} wert;

wert.d = 1.2345;
machen und dann mit
wert.u[0] ... wert.u[8]
die einzelnen Bytes abfragen. Dadurch überlässt Du dem Compiler die 
Pointer-Geschichte.

Autor: Herbert Knieling (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
danke, das union war der Befehl, den ich gesucht hatte.
Ist es so, dass Rundungen nur dann durchgeführt werden, wenn ich den Typ 
caste?

z.B.

double dWert = 12.6
int i = (int) dWert;

--> i = 12...

aber int* pI = (int*) &dWert

--> *pI = den Bits entsprechender Wert als int?

Autor: Florian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn Du den Compiler nötigst, aus dem double einen anderen Zahlentyp zu 
machen (also alle Varianten von int, alle Varianten von char oder auch 
andere Varianten von float), müssen natürlich die Zahlen angepasst 
werden, damit der Wert auch dargestellt werden kann.

Übrigens für Rundungen würde ich mir an Deiner Stelle mal die Funktionen 
ceil() und floor() anschauen.

Wenn ich mal unterstelle, dass die Länge Deines Ints 32 Bit beträgt 
(hängt von der Architektur ab), wird Dir *pI die ersten 32 Bit von dWert 
liefern. Allerdings ist der Wert nicht der, den Du mit dem ersten Cast 
(also 12) erhalten würdest, sondern das, was im Speicher steht.

Beispiel:

Nehmen wir an, die Variable dWert sei im Speicher an Stelle 0x1000 
gespeichert.

Der Speicher würde dann wie folgt aussehen:
0x33 0x33 0x33 0x33 0x33 0x33 0x29 0x40

int * pI = ( int * ) &dWert;
pI hat den Wert 0x1000, zeigt also auf den Speicher von dWert.

*pI würde Dir dann 0x33333333 liefern (falls int 32 Bit lang ist). Auch 
hier hängt die Reihenfolge von der Architektur ab (ausgerechnet bei 12.6 
sind allerdings die ersten 4 Bytes identisch) ---
s. http://de.wikipedia.org/wiki/Byte-Reihenfolge

Wenn Du anstatt int short verwendest (short = 16 Bit) würdest Du mit *pI 
0x3333 bekommen, mit char 0x33 usw. Wenn Du float anstatt int verwenden 
würdest, würde wohl auch irgendein Murks herauskommen.

Aber warum probierst Du das nicht einfach aus?


Wie bereits oben geschrieben:

http://de.wikipedia.org/wiki/IEEE_754

Hier ist der Aufbau der float-Typen beschrieben.


Autor: Herbert Knieling (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die Tipps...

Ich habe es inzwischen ausprobiert. Ich hatte übers Wochenende 
allerdings keinen Compiler zur Hand...

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.