2016-11-23 11 views
2

Я хотел бы выделить некоторую память, инициализировать ее для некоторых значений, а затем отличать разные сегменты этой памяти от разных структур. Что-то выглядит следующим образом:Литье памяти в объединение

union structA{ 
    __int8 mem[3]; 

    struct{ 
    unsigned field1 : 8; 
    unsigned field2 : 12; 
    unsigned field3 : 4; 
    }; 
}; 

struct structB{ 
    __int8 mem[10]; 
}; 


__int8 globalMem[128]; 

structA a1 <---- &globalMem[0] 
structA a2 <---- &globalMem[10] 
structB b1 <---- &globalMem[30] 

Я попытался с помощью reinterpret_cast, и я не получаю ошибку компилятора, но это, кажется, что мои переменные (a1, a2 и b1) на самом деле не назначены/инициализируется правильно.

Любое представление о том, почему это не работает и каков правильный способ добиться чего-то подобного?

Спасибо!

+4

Выравнивание битов и заполнение - это реализация. Вам нужно будет выяснить, добавил ли ваш компилятор дополнение к вашей структуре с битовыми полями. Очень вероятно. –

+0

Также использование подписанного базового типа ('__int8') может быть не лучшей идеей. –

+1

попробуйте обернуть вашу программу 'pragma pack (push, 1) PROGRAM pragma pack (pop)' Он должен устранить любые проблемы с заполнением, о которых говорил Сэм Варшавчик. – GoldenSpecOps

ответ

0

Чтобы добиться того, что вы собираетесь делать, требует использование reinterpret_cast:

structA a1 = *reinterpret_cast<structA*>(&globalMem[0]); 
structA a2 = *reinterpret_cast<structA*>(&globalMem[10]); 
structB b1 = *reinterpret_cast<structB*>(&globalMem[30]); 

Что случилось с этим?

Это требует крайней осторожности, так как C++ struct а есть особый вид class, и этот вид уступки не уважает объект семантического (потому что содержание в различных globalMem адресах не инициализируются как надлежащий объект, если вы» d используйте placement new где-нибудь в вашем коде).

Вы также можете быть уверены, что structA тривиально можно скопировать (is_trivially_copyable<structA>::value, к счастью, это правда), прежде чем использовать этот трюк.

Кроме того, может возникнуть проблема с ограничениями выравнивания, которые могут не соблюдаться, поскольку globalMem не имеет ограничений по выравниванию, но в зависимости от компилятора/архитектуры structA может потребовать выравнивания слов.

И, наконец, размер structA не обязательно 3, как вы склонны думать. На самом деле на некоторых компиляторах это будет 4, как и в this online demo

Дополнительные замечания

Вы можете использовать стандартные типы uint8_t вместо компилятора определенное имя типа, начиная с двойным подчеркиванием.

Что касается темы выравнивания и размера, я бы посоветовал вам быть очень осмотрительным в предположениях о размещении памяти. Я предпочел бы предложить вашему globalMem рассмотреть возможность создания структуры всех структур, которые он содержит, чтобы обеспечить правильный семантический объект и иметь безопасный макет.

+0

, но это только копирует часть globalMem в a1 и т. Д. Это действительно не «сопоставляет» a1, a2 и b1 с частями globalMem. – Ali

+0

@ У вас есть несколько проблем на вашем макете (см. Редактирование), что заставляет меня думать, что ваш контроль сопоставления принимает неверные предположения (начиная с размера структуры A). Я приглашаю вас посмотреть эту онлайн-демонстрацию: http://ideone.com/K3PYpT, где вы увидите, что объект, предварительно инициализированный prpeprly, правильно скопирован, несмотря на реинтерпрет. Тем не менее, переинтерпретировать бросок обычно показывает сложный дизайн, который стоит пересмотреть. – Christophe

 Смежные вопросы

  • Нет связанных вопросов^_^