Forum: Compiler & IDEs Float anschauen


von Peter Z. (Gast)


Lesenswert?

Hallo, ich möchte mir die innere Zahlendarstellung von float und 
double anschauen.

(Mein ATtiny84 kennt kein printf, ich habe nur ein kleines LC-Display)
Wie kann ich eine float absichtlich falsch in eine unsigned long 
Variable casten, um mir das in HEX anzeigen zu lassen?

von Einsteiger (Gast)


Lesenswert?

Du könntest ein memcpy machen und die Bytes mit printf (%x) ausgeben.

Grüsse,
René

von Dr. Sommer (Gast)


Lesenswert?

uint32_t converted = *((uint32_t*) &someFloat);

von Klaus W. (mfgkw)


Lesenswert?

und die dritte Standardmöglichkeit der Vollständigkeit halber:
eine union basteln mit einer float und einer uint32_t, dann an die float 
zuweisen und aus der uint32_t entnehmen.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Standardkonform ist die Verwendung von memcpy.  Weder die 2. noch der 3. 
Vorschlag sind standardkonform, wobei die Verwendung einer Union wie im 
Vorpost mit GCC funktioniert, aber nicht unbedingt mit anderen 
(standardkonformen) Compilern.

von Dr. Sommer (Gast)


Lesenswert?

casten und unions sind beide standardkonform, aber genau wie memcpy sind 
sie alle undefined behaviour. Das ergibt sich allein schon daraus dass C 
den Aufbau von floats nicht definiert. Sie sollten aber "zufällig" im 
GCC funktionieren...
Und falls der Compiler das memcpy nicht wegoptimiert kriegt ist das 
außerdem extrem ineffizient.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Dann lies mal nach über Strict Aliasing bevor du hier Tipps gibst.

von Rolf Magnus (Gast)


Lesenswert?

Dr. Sommer schrieb:
> casten und unions sind beide standardkonform, aber genau wie memcpy sind
> sie alle undefined behaviour. Das ergibt sich allein schon daraus dass C
> den Aufbau von floats nicht definiert.

Der Aufbau von float und der Aufbau von unsigned long. Erst die 
Kombination der beiden macht es undefiniert. Laut ISO C ist es nämlich 
durchaus erlaubt, ein beliebiges Objekt, also auch einen float, per 
memcpy in ein Array aus unsigned char zu kopieren, um auf diese Weise 
die Byte-Repräsentation zu bekommen.

> Und falls der Compiler das memcpy nicht wegoptimiert kriegt ist das
> außerdem extrem ineffizient.

Dann ist aber auch der Compiler extremer Murks.
gcc muß es noch nicht mal wegoptimieren, da es eh komplett im Compiler 
implementiert ist. Das heißt, daß es selbst bei ganz ausgeschalteten 
Optimierungen nicht zu einem Funktionsaufruf kommt.

Ich habe mal folgende 3 Varianten verglichen:
1
static inline unsigned long a(float f)
2
{
3
    return *(unsigned long*)&f;
4
}
5
6
static inline unsigned long b(float f)
7
{
8
    unsigned long ret;
9
    memcpy(&ret, &f, sizeof ret);
10
    return ret;
11
}
12
13
static inline unsigned long c(float f)
14
{
15
    union
16
    {
17
        float f;
18
        unsigned long u;
19
    } uf;
20
21
    uf.f = f;
22
    return uf.u;
23
}

Auf avr-gcc mit -O3 kommt bei allen drei exakt das gleiche raus. Bei dem 
für x86-64 ist die union-Variante eine Instruktion länger. Alles andere 
ist aber auch da gleich.
Was man hier aber schon sieht, ist daß vom Source-Code her die 
union-Variante irgendwie nach "von hinten durch die Brust in Auge" 
aussieht.

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.