Тип каламбура, 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).

Это вызывает предупреждение о разыменовывании указателя с символами типа, который нарушит строгие правила алиасинга.Я подумал, что это будет нормально, так как я использовал 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.

Но безопасно ли это?Мне кажется, что я пытался обойти проблему, а не решить ее. Для меня -> все еще каким-то образом разыменовывает переменную.

В качестве альтернативы, есть ли лучший способ добиться эффекта? т.е. получить модифицируемую ссылку (или указатель), приведенную из хранилища внутри другой структуры? (Union не будет работать, так как набор сохраняемых типов неизвестен, когда Aопределен, и некоторые из них могут быть добавлены через плагины, memcpyзаставит меня скопировать данные обратно и вперед, хотя пока это кажется единственно безопасным путем)

5
задан J.N. 3 April 2012 в 01:07
поделиться