我有一個旨在存儲用戶定義的數據(即從一個插件)的結構。它有一個這樣的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