有关编译器输出的异或浮点值和一般转换问题

时间:2018-11-07 23:52:53

标签: c++ c++11 gcc gcc-warning

好吧,这两个问题都与我的编译输出有关,因为我试图删除所有警告。

回答第一个问题
我将浮点值异或,编译器输出: 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被定义为该结构内部的浮点数。

有人知道如何解决警告吗? (我知道我可以禁用该警告,但我不知道如何获得警告的解决方案)

我的第二个问题是:
尽管只有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 个答案:

答案 0 :(得分:2)

为避免严格的别名冲突,代码可以是:

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