I'm trying to return float x, y and z angle values for a body object from my ODE (open dynamics engine) simulation.
float* Creature::eulerAngles(const float &q0, const float &q1, const float &q2, const float &q3){
float angles[3] = {atan2(2 * (q0*q1 + q2*q3), 1 - 2 * (q1*q1 + q2*q2)),
asin( 2 * (q0*q2 - q3*q1)),
atan2(2 * (q0*q3 + q1*q2), 1 - 2 * (q2*q2 + q3*q3))};
return angles;
}
Because dBodyGetQuaternion
returns 4 const float quaternions I need to then get the rotations and I've had immense difficulty trying to get it to compile. Now it does compile but I'm getting this warning.
Could anyone explain to me why and what it means please?
Solution. Since the problem is that the return address is actually of a local variable, the solution would be to dynamically allocate memory to a variable to hold the address and pass it to the function as a parameter. Now, the variable is declared outside the function block and is no longer a local variable.
a is an array local to the function. Once the function returns it does not exist anymore and hence you should not return the address of a local variable.
C++ How to return a local variable from a function? But there is a way to access the local variables of a function using pointers, by creating another pointer variable that points to the variable to be returned and returning the pointer variable itself.
float angles[3] = { ... };
defines a local array.
The statement
return angles;
returns a pointer to the first element of the array.
However, the array is destructed as soon as the function returns. Hence, the returned pointer is a dangling pointer.
That's what the compiler is warning you about. If you dereference the returned pointer in the calling function, you invoke undefined behavior.
In order to return a pointer to an array that will remain valid after the function returns, you need to allocate dynamic memory and return the dynamic memory.
float* Creature::eulerAngles(const float &q0, const float &q1,
const float &q2, const float &q3)
{
float* angles = new float[3];
angles[0] = atan2(2 * (q0*q1 + q2*q3), 1 - 2 * (q1*q1 + q2*q2));
angles[1] = asin( 2 * (q0*q2 - q3*q1));
angles[2] = atan2(2 * (q0*q3 + q1*q2), 1 - 2 * (q2*q2 + q3*q3));
return angles;
}
Keep in mind that if you do the above, you'll have to make sure to call delete []
on the returned pointer in the calling function.
To avoid the hassles of manually allocating and deallocating memory, you can use std::vector<float>
as your return type.
std::vector<float> Creature::eulerAngles(const float &q0, const float &q1,
const float &q2, const float &q3)
{
std::vector<float> angles(3);
angles[0] = atan2(2 * (q0*q1 + q2*q3), 1 - 2 * (q1*q1 + q2*q2));
angles[1] = asin( 2 * (q0*q2 - q3*q1));
angles[2] = atan2(2 * (q0*q3 + q1*q2), 1 - 2 * (q2*q2 + q3*q3));
return angles;
}
With this, memory management is done automatically for you.
Since the size of the array is fixed at 3, using std::array<float, 3>
is better than using std::vector<float>
:
std::array<float, 3> Creature::eulerAngles(const float &q0, const float &q1, const float &q2, const float &q3)
{
std::array<float, 3> angles;
angles[0] = atan2(2 * (q0*q1 + q2*q3), 1 - 2 * (q1*q1 + q2*q2));
angles[1] = asin( 2 * (q0*q2 - q3*q1));
angles[2] = atan2(2 * (q0*q3 + q1*q2), 1 - 2 * (q2*q2 + q3*q3));
return angles;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With