Xor'ing float value & general cast question concerning compiler output

Stefanx3

New Member
#1
Well, both questions are concerned towards my compiling output, since I try to remove all warnings..

To the first question:
I'm xor'ing float values, compiler output: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
Mã:
inline float ClassXY::GetFloat(void) const
{
    uint32_t xored = *(uint32_t*)&m_pParent->m_Value.m_fValue ^ (uint32_t)this; // compiler warning for this line
    return *(float*)&xored;
}
m_pParent is a pointer to this class ClassXY *m_pParent;
m_Value is a var of a struct and m_fValue is defined as a float inside the struct.

Any idea how to get around the warning? (I know that I can disable the warning, but I have no idea to get a clean solution to it)

My second qustion would be:
The scenario is nearly the same though, only with int. Compiler is talking about information loss: warning: cast from ‘const ClassXY*’ to ‘uint32_t {aka unsigned int}’ loses precision [-fpermissive]

Without the -fpermissive compiler flag, I wouldn't be able to compile..
Mã:
inline int ClassXY::GetInt(void) const
{
    return (int)(m_pParent->m_Value.m_nValue ^ (int)this); // compiler warning for this line
}
And again, any idea on how to fix this?
Or is it inpossible without warnings, what I'm trying to accomplish?

To give you all an idea what it is about: auto example = g_pClassXY->FindVar("example_var");
Then: float float_val = example->fValue; // direct access, value is wrong
To get the value right, the right approach would be: float float_val = example->GetFloat();

Thanks in advance!
 

Admin

Administrator
Thành viên BQT
#2
To avoid a strict aliasing violation, the code could be:
Mã:
static_assert( sizeof(float) <= sizeof(uint32_t), "size problem" );
uint32_t xored{};
memcpy(&xored, &m_pParent->m_Value.m_fValue, sizeof xored);
xored ^= reinterpret_cast<uint32_t>(this);

float ret;
memcpy(&ret, &xored, sizeof ret);
return ret;
However there are still some issues:

  • The code is ill-formed on a system where this is a 64-bit pointer.
  • The float values involved might be an invalid bit pattern for float, causing undefined behaviour.
If your intent is to "encrypt" a float, then the encrypted value should be stored as uint32_t or a byte array, not as float.

The first bullet point could be addressed by generating a random 32-bit mask for each instance, instead of using this; or using uintptr_t instead of uint32_t.
 
Top