Странная проблема приведения со структурой ТМ - PullRequest
0 голосов
/ 12 марта 2010

У меня есть следующая проблема приведения, когда моя структура данных sSpecificData содержит поле типа tm:

typedef struct
{
   unsigned char  data[10000];
} sDataBuffer;

typedef struct
{
   int                 m_Id;
   sDataBuffer         m_Data;
} sData;

typedef struct {
   int                       m_value1;
   int                       m_value2;
   tm                        m_Date;
} sSpecificData;

const int SPECIFIC_SVC_DATA_SIZE = sizeof(sSpecificData);

typedef struct {
   int                    m_Id;
   sSpecificData          m_Data;
} sMyData;

int main(void)
{
       sData svc;
       sMyData* ptr1 = (sMyData*) &svc;
       sSpecificData* ptr2;
       ptr2 = (sSpecificData*) &svc.m_Data;
       ptr1->m_Data.m_value1 = 90;
       ptr1->m_Data.m_value2 = 80;
       cout << ptr1->m_Data.m_value1 << endl;
       cout << ptr1->m_Data.m_value2 << endl;
       cout << ptr2->m_value1 << endl;
       cout << ptr2->m_value2 << endl;       
       return 0;
}

без поля "tm m_Date;" как часть sSpecificData, вывод правильный:

90
80
90
80

С полем "tm m_Date;" как часть sSpecificData, вывод неправильный:

90
80
0   <-- !
90  <-- !

Есть ли идея, почему мой пример не работает, когда в поле sSpecificData есть поле типа tm?

Спасибо!

Ответы [ 3 ]

2 голосов
/ 12 марта 2010

это связано со структурой упаковки. добавляя поле tm к sSpecificData, вы изменяете его из структуры с естественным выравниванием int (4 байта) на нечто, имеющее естественное выравнивание, которое выглядит как 8 байтов.

так что с tm как частью sSpecificData структура sMyData фактически является

typedef struct {
   int                    m_Id;
   // 4 bytes of padding inserted to align sSpecificData on an 8 byte boundary.
   sSpecificData          m_Data; // with tm, this has a alignment of 8
} sMyData;

это объясняет, что вы видите. Чтобы это исправить, вы можете добавить явное значение заполнения для sMyData AND в sData.

typedef struct
{
   int                 m_Id;
   int                 m_padding;
   sDataBuffer         m_Data; // this accepts structures with an alignment of up to 8 
} sData;

typedef struct {
   int                    m_Id;
   int                    m_padding;
   sSpecificData          m_Data; // with tm, this has a alignment of 8
} sMyData;

Или вы можете использовать #pragma pack(4) (если ваш компилятор c поддерживает это), чтобы принудительно исключить заполнение из sMyData, но это приведет к смещению tm, что не очень хорошая идея. см. этот связанный вопрос.

очень похожий вопрос возник сегодня о C #, но проблемы те же, хотя синтаксис для определения упаковки отличается) Размер структур в .NET

1 голос
/ 12 марта 2010

Обычно такие операции с памятью очень зависят от платформы.

Основная проблема заключается в том, что из-за выравнивания данных переменные в памяти могут располагаться не там, где вы ожидаете их.

0 голосов
/ 12 марта 2010

Помимо уже упомянутых проблем, ваш код также нарушает строгое правило псевдонимов, поэтому его поведение не определено.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...