Различие между структурой и союзом

Есть ли хороший пример, чтобы дать разницу между struct и a union? В основном я знаю, что struct использует всю память своего члена, а union использует наибольшее пространство памяти членов. Есть ли другая разница в уровне ОС?

Ответ 1

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

Чтобы дать конкретный пример их использования, я некоторое время работал над интерпретатором Scheme, и я по существу накладывал типы данных схемы на типы данных C. Это включало сохранение в структуре перечисления, указывающее тип значения и объединение, чтобы сохранить это значение.

union foo {
  int a;   // can't use both a and b at once
  char b;
} foo;

struct bar {
  int a;   // can use both a and b simultaneously
  char b;
} bar;

union foo x;
x.a = 3; // OK
x.b = 'c'; // NO! this affects the value of x.a!

struct bar y;
y.a = 3; // OK
y.b = 'c'; // OK

edit: Если вам интересно, какая настройка xb в 'c' изменяет значение xa на, с технической точки зрения это не определено. На большинстве современных машин символ равен 1 байту, а int - 4 байта, поэтому значение xb означает, что значение "c" также дает первый байт xa того же значения:

union foo x;
x.a = 3;
x.b = 'c';
printf("%i, %i\n", x.a, x.b);

печать

99, 99

Почему два значения одинаковы? Потому что последние 3 байта int 3 равны нулю, поэтому он также читается как 99. Если мы поместим большее число для xa, вы увидите, что это не всегда так:

union foo x;
x.a = 387439;
x.b = 'c';
printf("%i, %i\n", x.a, x.b);

печать

387427, 99

Чтобы более подробно ознакомиться с фактическими значениями памяти, задайте и распечатайте значения в шестнадцатеричном формате:

union foo x;
x.a = 0xDEADBEEF;
x.b = 0x22;
printf("%x, %x\n", x.a, x.b);

печать

deadbe22, 22

Вы можете четко видеть, где 0x22 перезаписал 0xEF.

НО

В C порядок байтов в int не определен. Эта программа перезаписала 0xEF с 0x22 на моем Mac, но есть и другие платформы, где она заменила бы 0xDE вместо этого, потому что порядок байтов, составляющих int, был отменен. Поэтому при написании программы вы никогда не должны полагаться на поведение перезаписи конкретных данных в объединении, поскольку оно не переносимо.

Для более чтений на упорядочении байт, проверить порядок байт.

Ответ 2

Здесь короткий ответ: структура - это структура записи: каждый элемент в структуре выделяет новое пространство. Итак, структура типа

struct foobarbazquux_t {
    int foo;
    long bar;
    double baz; 
    long double quux;
}

выделяет не менее (sizeof(int)+sizeof(long)+sizeof(double)+sizeof(long double)) байтов в памяти для каждого экземпляра. ( "По крайней мере", потому что ограничения выравнивания архитектуры могут заставить компилятор вставить конструкцию.)

С другой стороны,

union foobarbazquux_u {
    int foo;
    long bar;
    double baz; 
    long double quux;
}

выделяет один кусок памяти и дает четыре псевдонима. Итак, sizeof(union foobarbazquux_u) ≥ max((sizeof(int),sizeof(long),sizeof(double),sizeof(long double)), опять же с возможностью некоторого добавления для выравниваний.

Ответ 3

Есть ли хороший пример, чтобы дать разницу между "структурой" и "союзом"?

Мнимый протокол связи

struct packetheader {
   int sourceaddress;
   int destaddress;
   int messagetype;
   union request {
       char fourcc[4];
       int requestnumber;
   };
};

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

Профсоюзы в основном представляют собой низкоуровневые детали, основанные на наследии C как язык системного программирования, где иногда используются "перекрывающиеся" места хранения. Иногда вы можете использовать союзы для экономии памяти, где у вас есть структура данных, где только один из нескольких типов будет сохранен за один раз.

В общем, ОС не заботится и не знает о структурах и объединениях - они оба являются блоками памяти. Структура - это блок памяти, в котором хранятся несколько объектов данных, где эти объекты не перекрываются. Объединение представляет собой блок памяти, который хранит несколько объектов данных, но имеет только хранилище для самого большого из них и, таким образом, может хранить только один из объектов данных в любой момент времени.

Ответ 4

Как вы уже заявили в своем вопросе, основное различие между union и struct состоит в том, что члены union перекрывают память друг друга, так что размер объединения является одним, а члены struct размещаются один за другим (с дополнительным заполнением). между). Кроме того, профсоюз достаточно большой, чтобы вместить всех его членов, и иметь выравнивание, которое подходит всем его членам. Итак, допустим, что int может храниться только по 2-байтовым адресам и имеет ширину 2 байта, а long может храниться только по 4-байтовым адресам и имеет длину 4 байта. Следующий союз

union test {
    int a;
    long b;
}; 

может иметь sizeof 4 и требование выравнивания 4. И объединение, и структура могут иметь заполнение в конце, но не в их начале. Запись в структуру изменяет только значение записанного члена. Письмо члену профсоюза сделает значение всех остальных членов недействительным. Вы не можете получить к ним доступ, если не писали в них раньше, иначе поведение не определено. GCC предоставляет в качестве расширения, которое вы действительно можете прочитать от членов профсоюза, даже если вы не писали им последнее время. Для операционной системы не должно иметь значения, записывает ли пользовательская программа в объединение или в структуру. На самом деле это только проблема компилятора.

Другим важным свойством union и struct является то, что они позволяют указателю на них указывать на типы любого из его членов. Таким образом, следующее действительно:

struct test {
    int a;
    double b;
} * some_test_pointer;

some_test_pointer может указывать на int* или double*. Если вы приведете адрес типа test к int*, он фактически будет указывать на своего первого члена a. То же самое верно и для союза. Таким образом, поскольку объединение всегда будет иметь правильное выравнивание, вы можете использовать объединение, чтобы сделать указание на некоторый тип допустимым:

union a {
    int a;
    double b;
};

Этот союз действительно может указывать на int и double:

union a * v = (union a*)some_int_pointer;
*some_int_pointer = 5;
v->a = 10;
return *some_int_pointer;    

действительно действует, как указано в стандарте C99:

Объект должен иметь свое сохраненное значение, доступное только через выражение lvalue, которое имеет один из следующих типов:

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

Компилятор не будет оптимизировать v->a = 10; так как это может повлиять на значение *some_int_pointer (и функция вернет 10 вместо 5).

Ответ 5

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

Примером этого является анализ числа float с помощью union a struct с битовыми полями и a float. Я сохраняю номер в float, а позже я могу получить доступ к определенным частям float через struct. В этом примере показано, как union используется для просмотра разных углов.

#include <stdio.h>                                                                                                                                       

union foo {
    struct float_guts {
        unsigned int fraction : 23;
        unsigned int exponent : 8;
        unsigned int sign     : 1;
    } fg;
    float f;
};

void print_float(float f) {
    union foo ff;
    ff.f = f;
    printf("%f: %d 0x%X 0x%X\n", f, ff.fg.sign, ff.fg.exponent, ff.fg.fraction);

}

int main(){
    print_float(0.15625);
    return 0;
}

Посмотрите одинарная точность на wikipedia. Я использовал пример и магический номер 0.15625 оттуда.


union также может использоваться для реализации алгебраического типа данных, который имеет несколько альтернатив. Я нашел пример этого в книге "Реальный мир Хаскелл" О'Салливана, Стюарта и Герцена. Проверьте это в разделе Разделенный раздел.

Ура!

Ответ 6

" union" и " struct" являются конструкциями языка C. Говорить о разнице в уровне ОС между ними нецелесообразно, так как это компилятор, который создает другой код, если вы используете одно или другое ключевое слово.

Ответ 7

Да, основное различие между struct и union такое же, как вы заявили. Struct использует всю память своего члена, а объединение использует наибольшее пространство памяти членов.

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

union SIGSELECT
{
  SIGNAL_1 signal1;
  SIGNAL_2 signal2;
  .....
};

В этом случае процесс использует только самую высокую память всех сигналов. но если вы используете struct в этом случае, использование памяти будет суммой всех сигналов. Значительная разница.

Подводя итог, следует выбрать Union, если вы знаете, что вы обращаетесь к любому из членов за раз.

Ответ 8

Нетехнически означает:

Предположение: chair = блок памяти, people = variable

Структура. Если есть 3 человека, они могут сидеть в кресле своего размера соответственно.

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

Технически означает:

Нижеприведенная программа дает глубокое погружение в структуру и объединение вместе.

struct MAIN_STRUCT
{
UINT64 bufferaddr;   
union {
    UINT32 data;
    struct INNER_STRUCT{
        UINT16 length;  
        UINT8 cso;  
        UINT8 cmd;  
           } flags;
     } data1;
};

Total MAIN_STRUCT size = sizeof (UINT64) для bufferaddr + sizeof (UNIT32) для объединения + 32 бит для заполнения (зависит от архитектуры процессора) = 128 бит. Для структуры все члены получают блок памяти смежно.

Союз получает один блок памяти члена максимального размера (здесь его 32 бит). Внутри союза еще одна структура лежит (INNER_STRUCT), ее члены получают блок памяти общего размера 32 бита (16 + 8 + 8). В объединении могут быть доступны либо INNER_STRUCT (32-разрядный) член , либо данные (32 бит).

Ответ 9

У вас есть это, все. Но так, в принципе, какой смысл профсоюзов?

Вы можете разместить одно и то же содержимое местоположения разных типов. Вы должны знать тип того, что вы сохранили в объединении (так часто вы помещаете его в struct с тегом типа...).

Почему это важно? Не совсем для космической выгоды. Да, вы можете получить некоторые бит или сделать некоторые дополнения, но это не главное.

Это для безопасности типов, это позволяет вам выполнять какую-то "динамическую типизацию": компилятор знает, что ваш контент может иметь разные значения и точное значение того, как ваша интерпретация зависит от вас во время выполнения. Если у вас есть указатель, который может указывать на разные типы, вы ДОЛЖНЫ использовать объединение, иначе код может быть некорректным из-за проблем с псевдонимом (компилятор говорит себе "о, только этот указатель может указывать на этот тип, поэтому я могу оптимизировать из этих доступов...", и могут произойти плохие вещи).

Ответ 10

Структура распределяет общий размер всех элементов в ней.

Объединение выделяет столько памяти, сколько требует его наибольший член.

Ответ 11

Структура

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

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

struct emp
{
    char x;//1 byte
    float y; //4 byte
} e;

полная память: get = > 5 байт

union emp
{
    char x;//1 byte
    float y; //4 byte
} e;

полная память: get = 4 байт

Ответ 12

Использование союза Союзы часто используются, когда необходимы специализированные разговоры типов. Получить представление о пользе союза. Стандартная библиотека c/c не определяет функцию, специально предназначенную для записи коротких целых чисел в файл. Использование функции fwrite() приводит к чрезмерным накладным расходам для простой работы. Однако, используя объединение, вы можете легко создать функцию, которая записывает двоичный код короткого целого в файл по одному байту за раз. Я предполагаю, что короткие целые числа длиной 2 байта

ПРИМЕР:

#include<stdio.h>
union pw {
short int i;
char ch[2];
};
int putw(short int num, FILE *fp);
int main (void)
{
FILE *fp;
fp fopen("test.tmp", "wb ");
putw(1000, fp); /* write the value 1000 as an integer*/
fclose(fp);
return 0;
}
int putw(short int num, FILE *fp)
{
pw word;
word.i = num;
putc(word.c[0] , fp);
return putc(word.c[1] , fp);
}    

хотя putw(), который я назвал с коротким целым числом, можно было использовать putc() и fwrite(). Но я хотел показать пример, чтобы доминировать, как можно использовать союз

Ответ 13

В чем разница между структурой и объединением?

Ответ на короткое замыкание: отношение к распределению памяти. Объяснение: В структуре пространство памяти будет создано для всех членов внутри структуры. В объединительной памяти пространство будет создано только для члена, которому требуется наибольшее пространство памяти. Рассмотрим следующий код:

struct s_tag
{
   int a; 
   long int b;
} x;

union u_tag
{
   int a; 
   long int b;
} y;

Здесь внутри структуры и объединения есть два члена: int и long int. Объем памяти для int равен: 4 байта, а пространство памяти для длинного int: 8 в 32-разрядной операционной системе.

Итак, для struct 4 + 8 = будет создано 12 байт, а для объединения будет создано 8 байт

Пример кода:

#include<stdio.h>
struct s_tag
{
  int a;
  long int b;
} x;
union u_tag
{
     int a;
     long int b;
} y;
int main()
{
    printf("Memory allocation for structure = %d", sizeof(x));
    printf("\nMemory allocation for union = %d", sizeof(y));
    return 0;
}

Ссылка: http://www.codingpractise.com/home/c-programming/structure-and-union/

Ответ 14

Союзы пригодится при написании функции упорядочения байтов, которая приведена ниже. Это невозможно с помощью структур.

int main(int argc, char **argv) {
    union {
        short   s;
        char    c[sizeof(short)];
    } un;

    un.s = 0x0102;

    if (sizeof(short) == 2) {
        if (un.c[0] == 1 && un.c[1] == 2)
            printf("big-endian\n");
        else if (un.c[0] == 2 && un.c[1] == 1)
            printf("little-endian\n");
        else
            printf("unknown\n");
    } else
        printf("sizeof(short) = %d\n", sizeof(short));

    exit(0);
}
// Program from Unix Network Programming Vol. 1 by Stevens.

Ответ 15

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