xor'ing значение с плавающей точкой и общий вопрос о выводе компилятора

Ну, оба вопроса касаются моей компиляции, так как я пытаюсь удалить все предупреждения...

К первому вопросу:
Я xor'ing значения с плавающей точкой, вывод компилятора:warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]

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 - указатель на этот класс ClassXY *m_pParent;
m_Value - это переменная структуры, а m_fValue определяется как float внутри структуры.

Есть идеи, как обойти предупреждение? (Я знаю, что могу отключить предупреждение, но понятия не имею, чтобы найти для него чистое решение)

Мой второй вопрос будет:
Сценарий почти такой же, только с int. Компилятор говорит о потере информации: warning: cast from ‘const ClassXY*’ to ‘uint32_t {aka unsigned int}’ loses precision [-fpermissive]
Без флага компилятора -fpermissive я не смог бы скомпилировать..

inline int ClassXY::GetInt(void) const
{
    return (int)(m_pParent->m_Value.m_nValue ^ (int)this); // compiler warning for this line
}

И снова, есть идеи, как это исправить?
Или это невозможно без предупреждения, чего я пытаюсь достичь?

Чтобы дать вам представление о том, что это такое:auto example = g_pClassXY->FindVar("example_var");
Затем: float float_val = example->fValue; // direct access, value is wrong
Чтобы получить правильное значение, правильный подход будет следующим: float float_val = example->GetFloat();

Заранее спасибо!

1 ответ

Решение

Чтобы избежать строгого нарушения псевдонимов, код может быть:

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;

Однако есть еще некоторые проблемы:

  • Код плохо сформирован в системе, где this это 64-битный указатель
  • Используемые значения с плавающей точкой могут быть недопустимым битовым шаблоном для float, вызывая неопределенное поведение.

Если ваше намерение состоит в том, чтобы "зашифровать" число с плавающей точкой, то зашифрованное значение должно быть сохранено как uint32_t или байтовый массив, а не как float,

Первая точка может быть решена путем генерации случайной 32-битной маски для каждого экземпляра вместо использования this; или используя uintptr_t вместо uint32_t,

Другие вопросы по тегам