我有一个旨在存储用户定义的数据(即从一个插件)的结构。它有一个这样的char[]
与给定的最大大小来存储该数据。类型双引号,char []和解引用
struct A
{
// other members omitted
// data meant to be type punned, only contains PODs
char data[256];
};
然后有一个示例用户结构具有一个静态函数来从A
投射自己。
struct B
{
int i;
double d;
static B& FromA_ref(A& a)
{
// static_assert that sizeof(B) < sizeof(A::data)
return * reinterpret_cast<B*>(a.data);
}
};
我编译g++ -O3 -std=c++0x -Wall -o test test.cpp
(GCC 4.6.1)。
这会触发dereferencing type-punned pointer will break strict-aliasing rules
警告。我认为这样可以,因为我使用了char[]
作为存储,我认为它会遵循与char*
相同的规则。我发现它并不奇怪。你不是吗?那么......我现在不能改变它,所以让我们继续。
现在让我们来看看下面的方法:
struct B
{
....
static B* FromA_ptr(A& a)
{
// static_assert that sizeof(B) < sizeof(A::data)
return reinterpret_cast<B*>(a.data);
}
}
因为我不是在这里提领任何GCC不输出任何警告。当我稍后使用指向B
的指针时也不会。
A a;
auto b = B::FromA_ptr(a);
b->i = 2; // no warnings.
但是安全吗?我觉得我一直在解决问题而不是解决问题。对我来说,->
仍然以某种方式解引用变量。
另外,有没有更好的方法来实现效果? I.E.从另一个结构中的存储获得一个可修改的引用(或指针)? (Union不起作用,因为当定义了A
时,存储的类型集是不知道的,有些可能通过插件添加,memcpy
将迫使我来回复制数据,尽管它似乎是唯一安全的方式远)
我不是专家,但你在寻找'__may_alias__'属性吗? http://blog.worldofcoding.com/2010/02/solving-gcc-44-strict-aliasing-problems.html – 2012-04-03 01:14:36
无论如何,你如何处理对齐问题? – curiousguy 2012-07-11 07:12:56
@curiousguy:到目前为止我不,但我应该。尽管如此,在x86上我猜我可能会降低性能。我希望'__attribute __((aligned(8)));'因为我不想自动向量化任何东西,所以就够了。可能'may_alias'已经告诉GCC在做太多奇怪的事情之前要注意对齐。 – 2012-07-12 06:21:26