Hi, basically exactly as the title says, I'm pretty sure its just a matter of some bitwise operations, I'm just not entirely sure of exactly what I should be doing, and all searches return back "64 bit vs 32 bit" etc etc thanks
views:
301answers:
4
+8
A:
pack:
u32 x, y;
u64 v = ((u64)x) << 32 | y;
unpack:
x = (u32)((v & 0xFFFFFFFF00000000) >> 32);
y = (u32)(v & 0xFFFFFFFF);
Jack
2010-05-11 11:39:32
You don't need the explicit bitmasks when unpacking; `x = (u32)(v>>32); y = (u32)v;` does the job.
Mike Seymour
2010-05-11 13:26:40
+2
A:
The basic method is as follows:
uint64_t int64;
uint32_t int32_1, int32_2;
int32_1 = int64 & 0xFFFFFFFF;
int32_2 = (int64 & (0xFFFFFFFF << 32) ) >> 32;
// ...
int64 = int32_1 | (int32_2 << 32);
Note that your integers must be unsigned; or the operations are undefined.
Williham Totland
2010-05-11 11:41:02
+5
A:
Or this, if you're not interested in what the two 32-bits numbers mean:
u32 x[2];
u64 z;
memcpy(x,&z,sizeof(z));
memcpy(&z,x,sizeof(z));
lhf
2010-05-11 11:43:57
+1 for not introducing types and bitshifts. I'd prefer assignments over `memcpy` though.
Michael Krelin - hacker
2010-05-11 12:03:57
Goz, it's not about performance, it's about my (my!) perception of code beauty.
Michael Krelin - hacker
2010-05-11 12:41:05
+1
A:
Use a union and get rid of the bit-operations:
<stdint.h> // for int32_t, int64_t
union {
int64_t big;
struct {
int32_t x;
int32_t y;
};
};
assert(&y == &x + sizeof(x));
simple as that. big consists of both x and y.
Viktor Sehr
2010-05-11 11:47:20
+1 for the union, but it would be better to use standard fixed size types from `<stdint.h>`, i.e. `int32_t`, `int64_t`, since sizeof(long) and sizeof(long long) are not guaranteed to be any particular value.
Paul R
2010-05-11 12:13:32
What is an aliasing error? What should be avoided at all costs? The real problem I see here is that you can't guarantee `y` is not aligned away without taking extra measures.
Michael Krelin - hacker
2010-05-11 12:43:57
My mistake it leads to undefined behaviour. According to the spec, if you write to big you can't assume that x and y contain anything. The only member of the union that contains valid data is big. Most compilers DO support it but it IS undefined behaviour. You really are better off using a fixed size memcpy that any optimiser worth its salt will optimise out anyway.
Goz
2010-05-11 13:02:27
Well, you can't assume anything according to specs, because there's no anonymous structs in there ;-) So the statement about big being the only member containing data makes about as little sense. But it's not undefined behavior - it should be either compile error or working. And I'm yet to see the compiler that goes beyond warning user against it (I do believe such a compiler exists, of course).
Michael Krelin - hacker
2010-05-11 13:23:47
Viktor, not that it matters, but why do you add sizeof(*y*) to the address of x? ;-)
Michael Krelin - hacker
2010-05-11 13:24:28
@Goz: because of the anonymous struct?, or cant you guaranteed anything with union?
Viktor Sehr
2010-05-11 13:54:08
@Viktor: You can ONLY guarantee that the element you just wrote in is valid. ie if you do myUnion.big = 64; then the only defined way to get the value again is by looking at myUnion.big. Anything else is undefined.
Goz
2010-05-11 13:57:33
Actually, you're guaranteed to have syntax error, because there's no semicolon after struct ;-) Goz, you're confusing the hell out of everyone. Anonymous structs are indeed not standardized, but what the hell do you mean by being undefined? How can it be undefined if compiler accepts it? Can it possibly put another union member elsewhere?
Michael Krelin - hacker
2010-05-11 19:48:53
@Goz: could you give a usage example where the behavious is undefined? is the struct (could be replaced by an array[2]) or the union the problem=
Viktor Sehr
2010-05-11 20:46:28
Turning struct into array should please both Goz and standards and also rule out the possibility alignment troubles.
Michael Krelin - hacker
2010-05-12 06:55:31
@Everyone: Regardless of the anonymous-ness of any of those options if you write a value into big then the only defined way to get that value is through big. Using another entry in the union is undefined behaviour. It works on most compilers I totally agree but it is still undefined behaviour.
Goz
2010-05-12 08:46:30
@Goz: but is it undefined to assign values to x and y, pass big around as an int64, and extract x any back via a union? I can't see which operation is undefined?
Viktor Sehr
2010-05-12 08:59:50
Goz, now I see your point. Union guarantees that all of its members start at the same memory location. Which means, having `union { uint32_t big; uint16_t smalls[2]; uint8_t smallers[4]; };` yields perfectly defined (though architecture-dependent) behaviour.
Michael Krelin - hacker
2010-05-12 10:30:47