代码之家  ›  专栏  ›  技术社区  ›  doublep

严格的指针别名:通过“易失性”指针/引用访问是一种解决方案吗?

  •  8
  • doublep  · 技术社区  · 16 年前

    紧跟其后 a specific problem ,一个自我回答和评论,我想知道这是一个正确的解决方案,解决方法/黑客或只是一个明显的错误。

    具体来说,我重写了代码:

    T x = ...;
    if (*reinterpret_cast <int*> (&x) == 0)
      ...
    

    AS:

    T x = ...;
    if (*reinterpret_cast <volatile int*> (&x) == 0)
      ...
    

    用一个 volatile 指针的限定符。

    我们假设治疗 T 作为 int 在我的情况下是有道理的。这是通过 不稳定的 引用解决指针混叠问题?

    参考规范:

    [注:volatile是实现的一个提示,以避免攻击性 涉及对象的优化,因为对象的值可能 通过实现无法检测到的方法进行更改。见1.9 详细的语义。一般来说,volatile的语义是有意的 在C++中是相同的,因为它们在C。

    编辑:

    上面的代码至少在GCC4.5中解决了我的问题。

    2 回复  |  直到 13 年前
        1
  •  15
  •   sellibitze    16 年前

    volatile不能帮助您避免此处未定义的行为。所以,如果你和GCC合作的话,那就是运气。

    假设t是一个pod。那么,正确的方法是

    T x = …;
    int i;
    memcpy(&i,&x,sizeof i);
    if (i==0)
      …
    

    那里!没有严格的混叠问题和内存对齐问题。gcc甚至将memcpy作为一个内部函数来处理(在本例中不插入函数调用)。

        2
  •  -4
  •   curiousguy    14 年前

    volatile不能帮助您避免此处未定义的行为。

    嗯,关于 volatile 标准中有些不清楚。我基本上同意你的回答,但现在我想稍微不同意。

    为了理解 不稳定的 这意味着,对于大多数人来说,标准并不明确,尤其是一些编译器编写者。最好想想: 使用时 不稳定的 (而且只有当),C/C++是非常高级的汇编程序。 .

    当写信给 不稳定的 左值,编译器将发出一个存储,如果一个存储不够,将发出多个存储。( 不稳定的 不代表原子)。

    当写信给 不稳定的 左值,编译器将发出一个加载,如果一个加载不够,将发出多个加载。

    当然,如果没有显式加载或存储,编译器只会发出暗示加载或存储的指令。

    Sellibitze给出了最佳解决方案: 使用 memcpy 用于位重新解释。

    但是,如果对一个内存区域的所有访问都是用 不稳定的 左值, 很明显,严格的别名规则不适用 . 这是你问题的答案。

    推荐文章