0

To give some background, I'm coding the JVM for Java 8 in C, and I'm trying to print the Double value located in the Constant Pool.

I have two variables uint32_t that represent the high and low value of a double. I'm trying to print this double but I can't figure out what is wrong with my code.

I've tried printing all values to check.

uint64_t high_arg, low_arg, double_value;

high_arg = cp[cpIndex-1].info.Double.high_bytes; // value is = 0x0000000040000000
low_arg = cp[cpIndex-1].info.Double.low_bytes; // value is = 0x0000000000000000
double_value = (high_arg << 32) | low_arg; // value is = 0x4000000000000000
printf("%f\n", (double)double_value);

It prints double:4.61169e+18 but is was supposed to return 2

What am I missing?

  • _I have two variables uint32_t that represent the high and low value of a double_ ... in your code I see two `uint64_t` not two `uint32_t`, is this a typo? – David Ranieri May 21 '19 at 17:23
  • The `printf()` line converts the integer that represents the bit pattern for a double into a double, which isn't what you want. You'll need to do something like: `*(double *)&double_value`. – Jonathan Leffler May 21 '19 at 17:23
  • `double_value = (high_arg << 32) | low_arg;` takes the bits in `high_arg` and `low_arg` and puts them together into one 64-bit integer, and then it assigns that integer **value** to `double_value`. Since the bits have bit 62 set (bit 30 in `high_arg`), the result is 2\*\*32, which is about 4.61169e18. To make a `double` value from the bits, you need to set the **bytes** that represent the `double` to the **bytes** that are in the `Double` member. If there are no endianness issues involved, you can do this simply with `double x; memcpy(&x, &cp[cpIndex-1].info.Double, sizeof x);`. – Eric Postpischil May 21 '19 at 17:26
  • @KeineLust cp[cpIndex-1].info.Double.high_bytes and low_bytes are uint32_t type, and I'm casting it to uint64_t. Sorry for not clarifying that! – Gabriel Vasconcelos May 21 '19 at 17:34
  • @JonathanLeffler That worked out, thanks a lot!! – Gabriel Vasconcelos May 21 '19 at 17:35
  • Glad it worked. Don't turn on 'strict aliasing' checks — that expression will fail them. You might evade them by going via an intermediate `(char *)` cast: `*(double *)(char *)&double_value`, or the compiler might spot what you're doing and object (or, alternatively, it might not spot what you're doing and object). I've not investigated. Beware thin ice. – Jonathan Leffler May 21 '19 at 17:38
  • @EricPostpischil Now I see why it was printing that value! Thanks for explaining it so well!! – Gabriel Vasconcelos May 21 '19 at 17:40
  • The code in the question does not show the definition of `cp`, particularly the definition of the structure `Double`. In the future, include **all** relevant code in the question. Where there is too much code, rework the code into a manageable example. You should provide a [mcve]. – Eric Postpischil May 21 '19 at 17:45
  • @EricPostpischil Sure, it was my first question, thanks for clearing that out. – Gabriel Vasconcelos May 21 '19 at 17:48

1 Answers1

1

The sollution, as @JonathanLeffler wisely pointed out, was to cast the integer that represented the double as double pointer, and them print its content.

printf("%f", *(double *)&double_value);
  • 2
    `memcpy` is a proper way to do this in C. Aliasing via pointer conversion is not. In C, but not C++, reinterpretation can also be done with a union. – Eric Postpischil May 21 '19 at 18:01