Объединение struct создает мусор и общий вопрос о структурной номенклатуре - PullRequest
0 голосов
/ 17 мая 2010

Я читал об союзах на днях (сегодня) и пробовал примеры функций, которые пришли с ними. Достаточно просто, но результат был понятен и полная фигня.

Первый пример:

union Test
{ 
    int Int;

    struct
    {
        char byte1;
        char byte2;
        char byte3;
        char byte4;
    } Bytes;
};

, где предполагается, что int имеет 32 бита. После того, как я установил значение Test t; t.Int = 7; и затем cout

cout << t.Bytes.byte1 << etc...

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

Второй пример дал мне еще худшие результаты.

union SwitchEndian
{
    unsigned short word;

    struct
    {
        unsigned char hi;
        unsigned char lo;
    } data;
} Switcher; 

На мой взгляд, выглядит немного странно. Во всяком случае, из описания, которое он говорит, это должно автоматически сохранять результат в формате с высоким / меньшим порядком байтов, когда я устанавливаю значение как

Switcher.word = 7656; и звонит с cout << Switcher.data.hi << endl

Результатом этого были символы, даже не определенные в диаграмме ASCII. Не уверен, почему они появляются.

Наконец, у меня возникла ошибка, когда я попытался исправить пример, вместо того, чтобы поместить байты в конец структуры, расположив ее прямо рядом с ней. Так что вместо

struct {} Bytes;

Я хотел написать

struct Bytes {};

Это бросило мне большую ошибку. Какая разница между ними? Поскольку в C ++ не может быть безымянных структур, в то время казалось вполне очевидным, что байты, расположенные в начале и в конце, являются его именами. За исключением нет, это не весь ответ, я думаю. Что тогда?

Ответы [ 2 ]

3 голосов
/ 17 мая 2010

Звуковые сигналы и странные символы вызваны тем, что вы пытаетесь напечатать символьные представления десятичных чисел, в данном случае Управляющие символы ASCII . В первом примере (звуковые сигналы) вы печатаете ASCII 7, который является символом колокола .

Вы можете привести свои данные к int, чтобы распечатать фактическое десятичное представление, например ::

cout << (int)t.Bytes.byte1 << endl << (int)t.Bytes.byte2 << endl << (int)t.Bytes.byte3 << endl << (int)t.Bytes.byte4 << endl;

Вы можете сделать нечто подобное для вашего второго примера, чтобы увидеть десятичное представление этих unsigned char значений в памяти.

Причина различия заключается в том, что тип cout, basic_ostream, имеет несколько перегрузок для operator<< для различных основных типов.

Для вашей последней проблемы, какую ошибку компилятора вы получаете? При использовании VS2008 оба определения структуры прекрасно компилируются.

2 голосов
/ 17 мая 2010

Обратите внимание, что технически чтение из члена объединения, отличного от члена, который был последний раз записан в, приводит к неопределенному поведению, поэтому, если вы в последний раз присвоили значение Int, вы не сможете прочитать значение из Bytes (это обсуждается в StackOverflow, например, в этом ответе на другой вопрос ).

Крис Шмих дает хорошее объяснение того, почему вы слышите гудки и видите управляющие символы, поэтому я не буду повторять это.

Для вашего последнего вопроса, struct {} Bytes; объявляет экземпляр с именем Bytes безымянной структуры. Это похоже на поговорку:

struct BytesType {};
BytesType Bytes;

за исключением того, что вы не можете обратиться к BytesType в другом месте. struct Bytes {}; определяет структуру с именем Bytes, но не объявляет ее экземпляры.

...