okay recently I started programming in C++ I am fairly new but I have taken to it rather well in my opinion (though I do dislike the cout and cin thing the BASIC PRINT and INPUT just seem a bit more logical to me but I digress.)
I want to use union to do the following:
float a = 4.2;
int tmp = *(1 + (int *)&a);
I know that:
union
{
int y;
float t;
} u;
u.t = x;
u.y &= 0x7FFFFFFF;
return u.t;
is equivalent to
int y = (*(int *)&x) & 0x7FFFFFFF;
return *(float *)&y;
but how do I translate
float a = 4.2;
int tmp = *(1 + (int *)&a);
to a union?
sorry if this is something obvious but I have been stuck for 2 days trying to figure it out and going nowhere while doing a fair amount of research. to try to find the solution to the problem.
From what I understand, the results of doing this with unions is undefined (and therefore unreliable). The only valid way to use a union is to only read the last type written to. Therefore writing to the int and reading back the float could possibly give you unpredictable results.
Of course, most (all?) compilers handle unions in the way you expect them to. However I personally still feel that doing this kind of thing should be avoided. Even if you ignore the "possibly unreliable" aspect of it... doing this kind of thing also hurts code clarity.
All that said, this:
1 2
float a = 4.2;
int tmp = *(1 + (int *)&a);
will access out of bounds memory possibly resulting in an access violation. (The union is only big enough to hold 1 int or 1 float, yet you are trying to access a 2nd int, thereby stepping outside the bounds of the union)
if that is the case why on earth does this bit of code:
1 2 3 4 5 6 7 8 9
double Powapprox(double a, double b) //originally developed by Martin Ankerl
{
int tmp = (*(1 + (int *)&a));
int tmp2 = (int)(b * (tmp - 1072632447) + 1072632447);
double p = 0.0;
*(1+(int * )&p) = tmp2;
//p = p * a / 2.71828F ; failed attempt to auto correct the accuracy
return p;
}
(I know the above code works with GCC I have used it myself under that compiler the problem is I slightly prefer Visual C++ to do work on libraries.(
Thinking about it I would presume that it would only shift the code a byte (edit used to be bit here) in one direction not access a second integer or float value... I'll try bitshifts to remedy the problem and see if that works (though that is going to be difficult in it's own right to thoroughly test to ess if it fixes the problem)
Well there you're using a double, which is larger than a float (twice as large), so you have enough memory to access two ints. Your original example had a float which isn't large enough.
That code doesn't shift the data by a byte, it shifts it by sizeof(int), which is typically 4 bytes.
What you're doing is effectively this:
1 2 3 4 5 6 7 8 9 10 11 12
union
{
double d;
int i[2];
} u;
u.d = whatever;
// u.i[0] is the "low" 4 bytes of d
// u.i[1] is the "high" 4 bytes of d
// assuming the machine you're on is little endian
// and assuming the compiler you're using handles unions the way you
// want it to. Again, there's no guarantee.
A diagram to illustrate:
// a union with a double (and 2 ints):
| union size |
| |
+-----------------------+
| double |
+-----------+-----------+
| int[0] | int[1] |
+-----------+-----------+
// a union with a float (and 1 int):
| union size|
| | out of bounds - not part of the union
+-----------+ |
| float | V
+-----------+-----------+
| int[0] | int[1] |
+-----------+-----------+
But again -- there isn't any guarantee the compiler will make a union this way, so you're probably better off leaving the code like you have it now.
then do you have any tips on how to get it working correctly in Microsoft Visual C++ 2010 Express? I can get it working with G++ (using the -fno-strict-aliasing option) with MINGW but I cannot seem to get it to work right in MSVC. I came up with the union method to get around one of 2 problems but the other persists I was hoping there was an easy way to use unions to get around it but apparently not.