1

I don't know why the following casting in C++ gives different values

 double n = -1.342;
 cout << (uint64_t) n << endl; 
 cout <<  * (uint64_t *) &n << endl;

output:

18446744073709551615
13832094686727353926

Can someone please explain why different numbers are printed?

  • 6
    This first cast is an actual numeric cast, i.e. "make this double an unsigned integer". The second cast is an "interpret the bit pattern at this memory location as an unsigned integer, even though it is actually the bit pattern for a double". You can guess the rest from there. – dhke Jun 27 '21 at 08:02
  • Thank you, that was my guess too, but, I'm wondering why the first cast didn't print zero? since that's closer to -1.342 than that big positive number! – user14096467 Jun 27 '21 at 08:05
  • 2
    `18446744073709551615` is `2 ** 64 -1`, i.e. this is actually `(uint64_t)(int64_t)-1`. Somebody else will probably know the reference that the conversion sequence is `(uint64_t)(int64_t)(double)` ... – dhke Jun 27 '21 at 08:14
  • Unfortunately, I don't get your second comment. Is there any link from internet that I can read more about it? Thank you. – user14096467 Jun 27 '21 at 08:26
  • 1
    If you cast `-1.342` to `int64_t`, you get `-1`. The bits for the value `-1` of an `int64_t` is "all bits are equal to 1". If you cast that sequence of bits to `uint64_t` you get the number `2^64 - 1` because that's the value for 64 bits equal to one, without a sign. – gthanop Jun 27 '21 at 08:35
  • 1
    Look up [two's complement](https://en.wikipedia.org/wiki/Two%27s_complement) for more details on the usual (and recently guaranteed by C++20) signed integer representation. – user4581301 Jun 27 '21 at 08:39
  • @gthanop Thanks, but I always thought "actual numeric cast" tries its best to convert to a number very close to its previous (actual) value, like what you said, when casting -1.342 to int64_t, it converts it -1. Following this, casting from int64_t (or -1) to uint64_t it should convert it to 0? No? why it maintains the bit pattern for int64_t to uint64_t conversion suddenly? – user14096467 Jun 27 '21 at 08:44
  • Note that `-1.342` as `double` value also has 64 bits, which yields something like "not all bits are equal to 1", and if you take this sequence of bits and interpret it as `unit64_t` you will get `13832094686727353926` (second case). – gthanop Jun 27 '21 at 08:47
  • @user4581301 Thank you, I know what two's complement is. I don't know where I can find about "conversion sequence is (uint64_t)(int64_t)(double)...". – user14096467 Jun 27 '21 at 08:48
  • About the *actual numeric cast* you are saying: I am not exactly sure on how to answer that. It seems like simply the sign is ignored when casting from `int64_t` to `uint64_t`. I am not sure though why for example all negative values are not casted to `0`. – gthanop Jun 27 '21 at 08:52
  • @gthanop I see. I leave it as open question here, so if anyone could reply it later would be awesome! As mentioned by dhke, in the first cast, it first converts a double to int64_t then to uint64_t. Why it does NOT maintain the bit pattern for the first step (from double to int64_t) and converts it numerically, but in the second step (from int64_t to uint64_t) suddenly it maintains the bit pattern and does not try to convert it numerically to zero??? – user14096467 Jun 27 '21 at 09:01
  • By the way you may also have a look at [IEEE 754 rounding rules](https://en.wikipedia.org/wiki/IEEE_754#Rounding_rules) and [this](https://stackoverflow.com/questions/4975340/int-to-unsigned-int-conversion) question. What I am thinking is that the answer to your *actual numeric cast* may be because "this is the way they are designed to behave". But that really is just a guess. And it also does not answer again "why were they designed to behave like that?". – gthanop Jun 27 '21 at 09:14
  • Handy reading: [Explicit Cast (AKA: C-Style cast)](https://en.cppreference.com/w/cpp/language/explicit_cast). – user4581301 Jun 27 '21 at 09:14
  • The pointer-based approach has **undefined behavior** (see “strict aliasing”). The description given in other comments does explain why the behavior observed is *plausible*, but anything at all *could* happen. – Davis Herring Jun 27 '21 at 15:21

0 Answers0