Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Для новичков > union


Автор: icepro 13.3.2009, 02:29
люди приведите пожалуйста толковый пример где нужно использовать именно юнион, а то в нете да и на мсдн там какие-то фиговые пример, или то я не умен или я не пойму в каких именно ситуациях он лучше... заранее спасибо

Автор: Anikmar 13.3.2009, 03:32
ИМХО
В моей практике не случалось случая, когда было необходимо использовать union.

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

Автор: azesmcar 13.3.2009, 06:03
Цитата

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


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

Пример из жизни. Программе по предварительным расчетом максимум нужно будет отсылать
4 - маленьких числа или
2 - средних или
1 - большое

создаем
Код


struct
{
   char messageType;
   union
   {
      char[4] bytes;
      short[2] shorts;
      int integer;
   } params;
}


получается сэкономили на размере сообщения. Можно конечно всегда отправлять int, но зачем мучатся с приведениями типов если есть юнион?

Автор: mrbrooks 13.3.2009, 09:33
Цитата(Anikmar @  13.3.2009,  03:32 Найти цитируемый пост)
В моей практике не случалось случая, когда было необходимо использовать union.

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

Автор: azesmcar 13.3.2009, 09:36
Цитата

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


да, можно еще о приведении к битам рассказать smile тоже иногда помогает

Код

struct bits
{
    unsigned char a1:1;
    unsigned char a2:1;
    unsigned char a3:1;
    unsigned char a4:1;
    unsigned char a5:1;
    unsigned char a6:1;
    unsigned char a7:1;
    unsigned char a8:1;
};

union bb
{
    unsigned char byte;
    bits byte_bits;
};

Автор: annushka89 13.3.2009, 09:37
вот яркий пример (битовые поля), разбирайтесь 
Код


#include <stdio.h>

union CODE  // представление одного байта
{
    unsigned char ch;
    struct BYTE
    {
        unsigned b1:1;//младший бит
        unsigned b3:1;
        unsigned b4:1;
        unsigned b5:1;
        unsigned b6:1;
        unsigned b7:1;
        unsigned b8:1;//старший бит
    } byte;
};

void bin(unsigned char c) // печать в двоичном коде
{
    CODE code;
    code.ch=K;
    printf("Code %d\n",code.ch);
    printf("Bit numbers: 8 7 6 5 4 3 2 1 \n");
    printf("Bit values:  %d %d %d %d %d %d %d %d    ",
        code.byte.b8,
        code.byte.b7,
        code.byte.b6,
        code.byte.b5,
        code.byte.b4,
        code.byte.b3,
        code.byte.b2,
        code.byte.b1);
    printf("Number: %d\n",c);
}

unsigned char pack(unsigned char *ch,int n)
{
    CODE code;
    for(int i=0;i<n;i++)
    {
        switch(ch[i])
        {
          case 'a':
             switch(i)
             {
                case 0:
                  code.byte.b1=0;
                  code.byte.b2=0;
                  break;
                case 1:
                  code.byte.b3=0;
                  code.byte.b4=0;
                  break;
                case 2:
                  code.byte.b5=0;
                  code.byte.b6=0;
                  break;
                case 3:
                  code.byte.b7=0;
                  code.byte.b8=0;
                  break;
             }
             break;
          case 'b':
             switch(i)
             {
                case 0:
                  code.byte.b1=0;
                  code.byte.b2=1;
                  break;
                case 1:
                  code.byte.b3=0;
                  code.byte.b4=1;
                  break;
                case 2:
                  code.byte.b5=0;
                  code.byte.b6=1;
                  break;
                case 3:
                  code.byte.b7=0;
                  code.byte.b8=1;
                  break;
             }
             break;
          case 'c':
             switch(i)
             {
                case 0:
                  code.byte.b1=1;
                  code.byte.b2=0;
                  break;
                case 1:
                  code.byte.b3=1;
                  code.byte.b4=0;
                  break;
                case 2:
                  code.byte.b5=1;
                  code.byte.b6=0;
                  break;
                case 3:
                  code.byte.b7=1;
                  code.byte.b8=0;
                  break;
             }
             break;
          case 'd':
             switch(i)
             {
                case 0:
                  code.byte.b1=1;
                  code.byte.b2=1;
                  break;
                case 1:
                  code.byte.b3=1;
                  code.byte.b4=1;
                  break;
                case 2:
                  code.byte.b5=1;
                  code.byte.b6=1;
                  break;
                case 3:
                  code.byte.b7=1;
                  code.byte.b8=1;
                  break;
             }
             break;
        }
    }
    return code.ch;
}
            

int main()
{
    FILE *fp1,*fp2;
    fp1=fopen("source.txt","rb");
    fp2=fopen("target.txt","wb");

    int ch1,i=0;
    unsigned char ch,ch2[4];
    while((ch1=fgetc(fp1))!=EOF)
    {
        ch2[i++]=(unsigned char)ch1;
        if(i==4) {
            ch=pack(ch2,4);
            i=0;
            bin(ch);
            putchar('\n');
            fputc(ch,fp2);
        }
        
    }
    fcloseall();
    return 0;
}

Автор: mrbrooks 13.3.2009, 09:40
Цитата(azesmcar @  13.3.2009,  09:36 Найти цитируемый пост)
да, можно еще о приведении к битам рассказать

Согласный.  smile 
Так что union вещь хорошая - избегать ее совсем не стоит.

Автор: Dmi3ev 13.3.2009, 10:42
звук, например, можно представить так
Код

union MyVolume
{
  unsigned long Volume;
  struct
  {
    Word Left;
    Word Right;
  };
}volume;

Автор: Anikmar 13.3.2009, 11:56
Цитата

mrbrooks Согласный.   
Так что union вещь хорошая - избегать ее совсем не стоит.


Полностью согласен. И не предлагаю его избегать - просто лично мне он как-то был не нужен. Но если в языке есть конструкция и она подходит для решения задачи, зачем ее избегать (опять в голове навязчивый goto  smile  ).



Автор: mes 13.3.2009, 13:53
Цитата(azesmcar @  13.3.2009,  12:37 Найти цитируемый пост)
mes, ну почему же? о проблемах гото в чуть ли не в каждой книге говорится...зачем же ставить его на одну полку с union? 

В книжках часто упоминается, наверно потому, что goto пытаются пропихнуть везде (от лени или незнания) вместо циклов и функций, а использования union'a избегают.
А насчет одной полки Вы правы - union гораздо опаснее и требует большей ответственности и знаний  smile



Автор: bsa 13.3.2009, 15:32

M
bsa
Обсуждение goto выделено в отдельную тему


Добавлено @ 15:33
icepro, если ты получил ответ на свой вопрос, то пометь тему решенной

Автор: UniBomb 13.3.2009, 15:33
Дабы вернуть обсуждение в изначальное русло приведу пример из жизни. Может он (пример) и не блещет изяществом, но меня оно вполне устраивает.

Имею в программе вот такой юнион:

Код

volatile union
 {
  float mdfl[22];
  unsigned int mdui[45];
  char mdch[90];
  unsigned char mduc[90];
  unsigned char mdWorkSpace[90];
 } mdns; //MyBusNameSpace


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

Код

 for(int i = first, j = 4; i < (first+count); i++, j++)
  data_to_tran[j] = mdns.mdWorkSpace[i];


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

Автор: icepro 18.3.2009, 19:15
Всем спасибо! Четко и ясно!

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)