2017-09-03 5 views
0

In this question versuchte das OP einen schwer fassbaren Fehler in einem großen Programm zu isolieren. Er beobachtete einige double Werte und versuchte dann, sie hart als Eingabe für ein kleineres Testprogramm zu codieren. Die Idee ist großartig, um einen solchen Fehler zu isolieren.Zuweisung einer exakten Darstellung zu einem Gleitkommawert

Verfahren jedoch verletzt die String Aliasing-Regel gewählt, Einführen UB, so ist der Test vollständig unzuverlässig:

  1. Uhr in Debugger den Ausdruck:

    +------------------------+----------------------| 
    | Watch Expression  | Value    | 
    +------------------------+----------------------| 
    | *(long long int *)(&a) | 4594681439063077250 | 
    +------------------------+----------------------| 
    
  2. und weisen dann in das Testprogramm:

    double a; 
    *(long long int *)(&a) = 4594681439063077250; 
    

(Ich vermute stark) Er tat dies, um den genauen double Wert zu erhalten, Stück für Stück.

Die Frage: Wie zu einem Doppel den genauen Wert zuweisen - Bit für Bit - beobachtet in einer Debug-Sitzung?

+0

Warum meinst du "Stück für Stück". A Zahlen eine Zahl, wenn Sie die Nummer kennen und wissen, das Repräsentationsformat Sie wissen, wie es dargestellt wird. –

+0

Erlaubt es Ihr Debugging-Tool, die tatsächlichen Bits in der Variablen oder nur eine dezimale Darstellung zu sehen? – Beta

+0

Sie haben bereits geantwortet, dass dies ein _undefiniertes Verhalten_ bedeutet. Ich bezweifle, dass es einen Weg gibt, ohne _UB_ einzuführen. – user0042

Antwort

0

Dies kann durch die die Doppel als ein Array von char erreicht werden:

double as_double = 0.0; 
uint64_t as_uint64 = 4594681439063077250 ; 

static_assert(sizeof(double) == sizeof(uint64_t), ""); 
memcpy(&as_double, &as_uint64_t, sizeof(double)); 
0

Meine Interpretation der strengen Aliasing-Regel, sagt dieser

UB wäre
uint64_t x = 4594681439063077250; 
double * a = (double *) & x; 

Code ist in Ordnung.

4

Hexadecimal representation ist eine gute Möglichkeit, die genaue Bitdarstellung eines Gleitkommawerts zuzuweisen. Wenn Sie keine Literale verwenden können, weil Sie noch nicht in C++ 17 sind, beachten Sie, dass strtod dieses Format erkennt.

+1

Seit C + 11 können Sie ['std :: hexfloat'] (http://en.cppreference.com/w/cpp/io/manip/fixed) mit' <<' and '>> 'Stream-Operatoren verwenden. – rici

Verwandte Themen