Почему выходные данные отличаются от ожидаемых в этом коде? - PullRequest
0 голосов
/ 25 мая 2019

Я изучаю C структуры и объединения, и я наткнулся на этот код.Насколько я знаю, union работает как объекты, поэтому printf должен быть таким же, как a, b, c, d

#include <stdio.h>

union Type {
    char A[2];
    struct{
        char B;
        char C;
    };
};

int main(){

    Type Data;
    Data.A[0] = 'a';
    Data.A[1] = 'b';
    Data.B = 'c';
    Data.C = 'd';

        printf("%c %c %c %c \n", Data.A[0], Data.A[1], Data.B, Data.C);
    return 0;
}

Почему выходные данные на самом деле не a, b, c, d?

1 Ответ

1 голос
/ 25 мая 2019

С Тип соединения

В C и C++, непомеченные объединения выражаются почти точно так же, как структуры (структуры), except that each data member begins at the same location in memory.

А размер союзов - это размер самого большого элемента объединения.В вашем случае

union Type {
    char A[2];
    struct{
        char B;
        char C;
    };
};

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

Когдаэти два оператора

Data.A[0] = 'a';
Data.A[1] = 'b';

выглядят как

      A[0]                  A[1]
 -------------------------------------------
|      'a'         |        'b'            |
 -------------------------------------------
       B                    C   
0x100              0x101
  |
 lets assume 0x100 as base address of union

, и если вы обращаетесь к Data.A[0] и Data.B, оба получают отпечатки как a как Data.A[0] и Data.B начинает доступ к данным с начального адреса, т.е. 0x100.Также Data.A[1] и Data.C будут печатать так же, как и те, кто обращается к данным из 0x101 ячейки памяти.

Когда ниже этих двух операторов

Data.B = 'c';
Data.C = 'd';

выполняется, это выглядит как

               A[0]                       A[1]
 ------------------------------------------------------------------
|      'c' (overwritten 'a')  |    'd'(overwritten 'b')            |
 -------------------------------------------------------------------
               B                              C   
0x100                         0x101
  |
 lets assume 0x100 as base address of union

Теперь, если вы печатаете как Data.A[0], так и Data.B, он печатает данные в ячейке памяти 0x100, а это c, поскольку более ранние данные перезаписываются.Точно так же Data.A[1] и Data.C печатает d.

...