Diferença entre uma estrutura e uma União

Existe algum bom exemplo para dar a diferença entre um "tubo" e um "sindicato"? Basicamente, eu sei que o "estructo" utiliza toda a memória do seu membro e o "sindicato" utiliza o maior espaço de memória dos membros. Existe alguma outra diferença de nível de SO?

Solução

Com um sindicato, você'é suposto utilizar apenas um dos elementos, porque eles'são todos armazenados no mesmo local. Isto torna-o útil quando se pretende armazenar algo que pode ser de vários tipos. Uma estrutura, por outro lado, tem um local de memória separado para cada um dos seus elementos e todos eles podem ser utilizados de uma só vez.

Para dar um exemplo concreto da sua utilização, estava a trabalhar num intérprete do Esquema há pouco tempo e estava essencialmente a sobrepor os tipos de dados do Esquema aos tipos de dados C. Isto implicava armazenar numa estrutura um enumero indicando o tipo de valor e um sindicato para armazenar esse valor.

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: Se você'está a perguntar-se que ajuste x.b para 'c' muda o valor de x.a para, tecnicamente falando, para's indefinido. Na maioria das máquinas modernas um char é 1 byte e um int é 4 bytes, dando assim x.b o valor 'c' também dá o primeiro byte de x.a o mesmo valor:

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

gravuras

99, 99

Porque são os dois valores os mesmos? Porque os últimos 3 bytes do int 3 são todos zero, por isso também lemos como 99. Se colocarmos um número maior para x.a, você'verá que nem sempre é esse o caso:

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

gravuras

387427, 99

Para ver mais de perto os valores reais da memória, deixe's definir e imprimir os valores em hexadecimal:

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

gravuras

deadbe22, 22

Pode-se ver claramente onde o 0x22 sobregravou a 0xEF.

MAS**

Em C, a ordem dos bytes num int são não definidos. Este programa substituiu a 0xEF por 0x22 no meu Mac, mas existem outras plataformas onde substituiria a 0xDE porque a ordem dos bytes que compõem o int foi invertida. Portanto, ao escrever um programa, nunca se deve confiar no comportamento de sobrescrever dados específicos num sindicato, porque ele's não é portátil.

Para mais leituras sobre a encomenda de bytes, verificar endianness.

Comentários (12)

"união" e "estruto" são construções da língua C. Falando de "nível" a diferença entre eles é inapropriada, uma vez que é's o compilador* que produz código diferente se se usar uma ou outra palavra-chave.

Comentários (0)

Uma estrutura atribui o tamanho total de todos os elementos que a compõem.

Um sindicato apenas atribui tanta memória quanto o seu maior membro necessita.

Comentários (1)