答案 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)
不小心使用模板会导致膨胀。但你完全忽略了这一点。
你根本没有想到这一点。模板的优势远远超过可执行大小的几kb。
值得注意的是,代码在Visual Studio 2010上按预期工作。