0

In this question the OP tried to isolate an elusive bug in a big program. He observed some double values and then tried to hard code them as input to a smaller test program. The ideea is great for isolating such a bug.

The method chosen however violates the String Aliasing rule, introducing UB, thus the test is completely unreliable:

  1. watch in debugger the expression:

    +------------------------+----------------------|
    | Watch Expression       | Value                |
    +------------------------+----------------------|
    | *(long long int *)(&a) | 4594681439063077250  |
    +------------------------+----------------------|
    
  2. and then assign it in the test program:

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

(I strongly suspect) He did this in order to preserve the exact double value, bit by bit.

The question: How to assign to a double the exact value - bit by bit - observed in a debug session?

bolov
  • 72,283
  • 15
  • 145
  • 224
  • Why do you mean "bit by bit". A numbers a number, if you know the number and know the representation format you know how its represented. – Nick is tired Sep 03 '17 at 23:11
  • Does your debugging tool allow you to see the actual bits in the variable, or just a decimal representation? – Beta Sep 03 '17 at 23:11
  • You already answered that this is introducing _undefined behavior_. I doubt there's a way without introducing _UB_ actually. – user0042 Sep 03 '17 at 23:17
  • 1
    Deep copy? Representing double as bytes should be legal. – user7860670 Sep 03 '17 at 23:18
  • "Undefined behavior" means **only** that the language definition does not tell you what the program does. It does not require that bad things happen and it does not make code "completely unreliable".. You're certainly right to look for a better way, but sometimes that's the best you can do. – Pete Becker Sep 03 '17 at 23:27
  • A lot of the friction on floating point values comes from converting between decimal and binary. As your source code is probably decimal it has to be converted, so there may be some slight shifts. Why not use numbers that don't shift when converted from decimal? – tadman Sep 03 '17 at 23:37
  • @PeteBecker It does, however, make the code dependent on a particular implementation (possibly even a version of that implementation). – cdhowie Sep 03 '17 at 23:38

3 Answers3

4

Hexadecimal representation is a good way to assign the exact bit representation of a floating point value. If you cannot use literals because you are not yet on C++ 17, note that strtod recognizes this format.

Jeff Garrett
  • 5,863
  • 1
  • 13
  • 12
  • 1
    Since C+11, you can use [`std::hexfloat`](http://en.cppreference.com/w/cpp/io/manip/fixed) with `<<` and `>>` stream operators. – rici Sep 04 '17 at 02:11
0

This can be accomplished by representing the double as an array of char:

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

My interpretation of the Strict Aliasing rule, says this would be UB

uint64_t x = 4594681439063077250;
double * a = (double *) & x;

your code is fine.

brian beuning
  • 2,836
  • 18
  • 22