0

I have a union defined as follows:

union V64
{
    double f64;
    __int64 i64;
    unsigned __int64 u64;
};

I'd like to do a lazy comparison (equality and inequality) of a 8-byte value of unknown type against another V64 of known type. Will comparing the i64 of two V64s consistently give me the expected result, regardless of the underlying type? For example:

V64 a.u64 << 9007199254740993+500;  //pseudo-code reading raw bytes
V64 b.u64 << -9007199254740993-501; //pseudo-code reading raw bytes
if(a.i64 > b.i64)
{/*do stuff*/}

Comparing u64 breaks down when one is negative and f64 breaks down when the value exceeds double's int storage (2^53 +1). Comparing i64 appears to work, but there might be a case I haven't considered.

Community
  • 1
  • 1
Phlucious
  • 3,704
  • 28
  • 61

1 Answers1

4

After you assign to two members of the same type, you can compare them:

a.f64 = 5.0;
b.f64 = -1.0;

if (a.f64 < b.f64) { /* ... */ }

You can only read the union member that was last written to. So you could compare a.f64 and c.u64, but that would just promote both values to double.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • Thank you for the reply. What do you mean I can only read the member last written to? See my question's edits for some clarification. – Phlucious Apr 18 '13 at 20:54
  • @Phlucious: It is undefined behaviour to read an inactive union member (i.e. any which wasn't the last to be written to). – Kerrek SB Apr 18 '13 at 21:03
  • Ah, I see. So even though it _appears_ to work on MSVC2010, it might not on gcc? Also, I just fixed a typo in the example. – Phlucious Apr 18 '13 at 21:39
  • So what's the alternative for truly "correct" code? A `void*` with `reinterpret_cast`? – Phlucious Apr 18 '13 at 22:19
  • @Phlucious: Err.. not write code like that? I don't know. What's the problem we're trying to solve? – Kerrek SB Apr 18 '13 at 22:28
  • lol, fair enough. I want to read 8+8 bytes from disc, which can be two `UINT64`s, two `INT64`s, or two `double`s, and then compare the two values against each other to know which is greater without writing 3 different comparisons. I get the results using the union by reading as a UINT64 and comparing as a INT64, but apparently that behavior is undefined C++. I'm not worried about endian-ness. – Phlucious Apr 18 '13 at 23:21
  • 1
    @Phlucious: Going just by what you said, that makes no sense. *How* do you know whether you're reading an int or a double? Once you know that, everything else will fall into place (i.e. read directly into the correct type). – Kerrek SB Apr 19 '13 at 07:47
  • @Phlucious: This strikes me as a classical XZ problem: You're asking about X, even though you think that you want to solve Y, but in truth you need to solve Z. – Kerrek SB Apr 19 '13 at 07:50
  • Went back through my old questions and found this answer I never accepted. Basically, I was trying to use unions in an undefined way. – Phlucious Jul 23 '13 at 15:52