如何解决指针别名问题?

时间:2010-09-09 08:09:21

标签: c++ pointers pointer-arithmetic

2 个答案:

答案 0 :(得分:3)

您是否关闭了警告?你应该有一些“解除引用类型的惩罚指针违反了严格的别名”,因为这正是你所做的(void **)Ptr_Add(...

编译器可以自由地假设指向不同类型的指针不是别名(使用一些execpitions),并且会产生优化的代码,用于缓存寄存器中指针的目标。为避免这种情况,您必须使用联合在不同的指针类型之间进行转换。引自http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#Optimize-Options

  

特别是,假设一种类型的对象永远不会与不同类型的对象驻留在同一地址,除非类型几乎相同。例如,unsigned int可以为int设置别名,但不能为void *或double。字符类型可以是任何其他类型的别名。

     

特别注意这样的代码:

     union a_union {
        int i;
        double d;
      };

     int f() {
        union a_union t;
        t.d = 3.0;
        return t.i;
      }
     

从不同的工会成员阅读的做法比最近写的那个(称为“打字式”)很常见。即使使用-fstrict-aliasing,也允许使用类型 - 双关语,前提是通过联合类型访问内存。因此,上面的代码将按预期工作。请参阅结构联合枚举和位字段实现。但是,此代码可能不会:

     int f() {
        union a_union t;
        int* ip;
        t.d = 3.0;
        ip = &t.i;
        return *ip;
      }
     

类似地,通过获取地址,转换结果指针和取消引用结果的访问具有未定义的行为,即使转换使用联合类型,例如:

     int f() {
        double d = 3.0;
        return ((union a_union *) &d)->i;
      }

在-O2,-O3,-Os级别启用-fstrict-aliasing选项。

在您的情况下,您可以使用类似

的内容
union {
    void** ret_ptr;
    ptrdiff_t in_ptr;
}

但是ptr_add中的代码看起来很糟糕; - )

或者只使用“fno-strict-aliasing”禁用此特定优化。更好地修复你的代码; - )

答案 1 :(得分:0)

不小心使用模板会导致膨胀。但你完全忽略了这一点。

  • 模板在使用时会导致膨胀 不小心,不小心。
  • 运行时错误的数量 模板避免了大量工作。
  • 模板化代码的速度很快 大于非模板化代码。
  • 除非您在嵌入式系统上运行,否则可执行文件的大小绝对是微不足道的。
  • STL提供了一个地图容器(二元搜索树)供您使用。

你根本没有想到这一点。模板的优势远远超过可执行大小的几kb。

值得注意的是,代码在Visual Studio 2010上按预期工作。