typedef — c ++: union — & gt; структура, объяснение?

У меня есть следующее определение типа:

typedef union{
unsigned int Entry;
struct {
unsigned char EntryType;
unsigned char EntryOffset[3];
};
} TLineDescriptor;

У меня также есть следующее использование типа:

TLineDescriptor LineDescriptor;
LineDescriptor.Entry = 40;
LineDescriptor.EntryType = 0x81;

sizeof(LineDescriptor) показывает, что эта переменная занимает 4 байта памяти, что вначале я предполагал, что она содержит либо int, либо struct.

cout << LineDescriptor.Entry << " " << LineDescriptor.EntryType << endl;

Тем не менее, строка выше печатает два разных значения, а именно 129 ü, LineDescriptor.Entry по-видимому, относится к области памяти, где было сохранено значение 0x81. Я не уверен, что случилось с 40.
Но ясно, что мое предположение было неверным. Может ли кто-то правильно интерпретировать и объяснить определение типа? Понимание этого крайне важно для меня, чтобы работать с кодом, который я нашел.

Заранее спасибо.

1

Решение

Это не разные значения, на самом деле. 129 код символа для символа ü, operator << из ostream лечит int а также char типы данных по-разному, печатая числовое значение для первого и символьное значение для последнего.

Итак, ваше понимание типов объединений верно. Тем не менее, обратите внимание, что при работе с типами union может возникнуть проблема с порядком байтов. Например, на машинах с прямым порядком байтов EntryType будет содержать наименее значимый байт Entry и EntryOffset массив других. Но на машинах с прямым порядком байтов, EntryType будет содержать самый значимый байт.

1

Другие решения

Ваше предположение не так, профсоюз проведет или Int или структура. Когда вы назначаете значение 0x81 в поле EntryType — целое число, которое вы ранее присвоили Entry будет перезаписано, поэтому, когда вы cout В обоих полях вы получите одинаковое количество, отображаемое для обоих: одно как int (129), а другое как char (ü). Оба имеют шестнадцатеричное значение 0x81,

1

Это держит int и struct на так же время, и оба занимают одно и то же пространство памяти. Получив доступ TLineDescriptor::EntryВы интерпретируете эти 4 байта как int, Если вы получаете доступ к нему через structВы интерпретируете это как 4 unsigned chars.

LineDescriptor.Entry = 40;

Это устанавливает 4 байта в int значение 40. В системе с прямым порядком байтов это означает, что первый байт равен 40, остальные 3 байта равны 0.

LineDescriptor.EntryType = 0x81;

Это устанавливает первый байт в значение 129 (0x81). (В системе с прямым порядком байтов это означает, что значение Entry теперь также 129, при условии, что для остальных установлено значение 0).

Что касается другого вывода: когда вы выводите EntryType, он отображается в виде символа, а не числа. Пытаться:

cout << LineDescriptor.Entry << " " << static_cast<int>(LineDescriptor.EntryType) << endl;
1

Напечатайте EntryType следующим образом:

cout << "0x" << hex << (unsigned)LineDescriptor.EntryType << endl;

и вы увидите, что ü равно 0x81.

Печать этого:

cout << LineDescriptor.Entry

является неопределенным поведением — потому что только один элемент в объединении может быть «активным» в данный момент — и ваше последнее назначение было EntryType.

Однако если предположить, что мы можем предположить, что это на самом деле не так неопределенно, как хотелось бы C ++, тогда 129 получен из:

Entry=40 — который в двоичном формате в вашей системе 28 00 00 00 (младший байт первый).

С LineDescriptor.EntryType = 0x81; Вы изменили первый байт: 81 00 00 00 — так что ваша распечатка для Entry теперь 129.

Проведите этот эксперимент, и вы получите другой результат:

TLineDescriptor LineDescriptor;

LineDescriptor.Entry = 256;
LineDescriptor.EntryType = 0x81;

cout << LineDescriptor.Entry << " " << unsigned(LineDescriptor.EntryType)
<< endl;
>> 385  129
1
По вопросам рекламы [email protected]