Com uma união, você deve usar apenas um dos elementos, porque todos eles são armazenados no mesmo local. Isso o torna útil quando você deseja armazenar algo que pode ser de vários tipos. Uma estrutura, por outro lado, possui um local de memória separado para cada um de seus elementos e todos eles podem ser usados ao mesmo tempo.
Para dar um exemplo concreto de seu uso, eu estava trabalhando em um intérprete de Scheme há pouco tempo e estava essencialmente sobrepondo os tipos de dados Scheme nos tipos C. Isso envolvia armazenar em uma estrutura uma enum indicando o tipo de valor e uma união 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á se perguntando para que configuração xb como 'c' altera o valor de xa, tecnicamente falando é indefinido. Na maioria das máquinas modernas, um caractere é de 1 byte e um int é de 4 bytes, portanto, fornecer a xb o valor 'c' também fornecerá o primeiro byte de xa com o mesmo valor:
union foo x;
x.a = 3;
x.b = 'c';
printf("%i, %i\n", x.a, x.b);
impressões
99, 99
Por que os dois valores são os mesmos? Como os últimos 3 bytes do int 3 são todos zero, também é lido como 99. Se colocarmos um número maior para xa, você verá que esse nem sempre é o caso:
union foo x;
x.a = 387439;
x.b = 'c';
printf("%i, %i\n", x.a, x.b);
impressões
387427, 99
Para ter uma visão mais detalhada dos valores reais da memória, vamos definir e imprimir os valores em hexadecimal:
union foo x;
x.a = 0xDEADBEEF;
x.b = 0x22;
printf("%x, %x\n", x.a, x.b);
impressões
deadbe22, 22
Você pode ver claramente onde o 0x22 substituiu o 0xEF.
MAS
Em C, a ordem dos bytes em um int não está definida. Este programa substituiu o 0xEF por 0x22 no meu Mac, mas há outras plataformas em que ele substituiria o 0xDE porque a ordem dos bytes que compõem o int foi revertida. Portanto, ao escrever um programa, você nunca deve confiar no comportamento de substituir dados específicos em uma união porque não é portátil.
Para mais informações sobre a ordenação de bytes, consulte endianness .
Aqui está a resposta curta: uma estrutura é uma estrutura de registro: cada elemento na estrutura aloca novo espaço. Então, uma estrutura como
aloca pelo menos
(sizeof(int)+sizeof(long)+sizeof(double)+sizeof(long double))
bytes na memória para cada instância. ("Pelo menos" porque as restrições de alinhamento da arquitetura podem forçar o compilador a preencher a estrutura.)Por outro lado,
aloca um pedaço de memória e fornece quatro aliases. Então
sizeof(union foobarbazquux_u) ≥ max((sizeof(int),sizeof(long),sizeof(double),sizeof(long double))
, novamente com a possibilidade de alguma adição para alinhamentos.fonte
Um protocolo de comunicação imaginário
Nesse protocolo imaginário, foi especificado que, com base no "tipo de mensagem", o seguinte local no cabeçalho será um número de solicitação ou um código de quatro caracteres, mas não ambos. Em resumo, os sindicatos permitem que o mesmo local de armazenamento represente mais de um tipo de dados, onde é garantido que você deseje armazenar apenas um dos tipos de dados a qualquer momento.
Os sindicatos são em grande parte um detalhe de baixo nível baseado na herança de C como uma linguagem de programação do sistema, onde locais de armazenamento "sobrepostos" são às vezes usados dessa maneira. Às vezes, você pode usar uniões para economizar memória, onde você possui uma estrutura de dados em que apenas um dos vários tipos será salvo ao mesmo tempo.
Em geral, o sistema operacional não se importa ou conhece estruturas e uniões - ambos são simplesmente blocos de memória para ele. Uma estrutura é um bloco de memória que armazena vários objetos de dados, nos quais esses objetos não se sobrepõem. Uma união é um bloco de memória que armazena vários objetos de dados, mas possui apenas armazenamento para o maior deles e, portanto, pode armazenar apenas um dos objetos de dados a qualquer momento.
fonte
packetheader ph;
solicitação de acesso?ph.request.requestnumber
?Como você já declarou em sua pergunta, a principal diferença entre
union
estruct
é que osunion
membros cobrem a memória um do outro, de modo que o tamanho da união seja o mesmo, enquanto osstruct
membros são dispostos um após o outro (com preenchimento opcional no meio). Além disso, um sindicato é grande o suficiente para conter todos os seus membros e ter um alinhamento adequado a todos os seus membros. Então, digamosint
que só pode ser armazenado em endereços de 2 bytes e tem 2 bytes de largura, e o comprimento só pode ser armazenado em endereços de 4 bytes e tem 4 bytes. A seguinte uniãopoderia ter um
sizeof
de 4 e um requisito de alinhamento de 4. Tanto uma união quanto uma estrutura podem ter preenchimento no final, mas não no início. Gravar em uma estrutura altera apenas o valor do membro gravado. Escrever para um membro de um sindicato invalidará o valor de todos os outros membros. Você não pode acessá-los se não tiver escrito antes, caso contrário, o comportamento é indefinido. O GCC fornece como uma extensão que você pode realmente ler dos membros de um sindicato, mesmo que não tenha escrito para eles mais recentemente. Para um sistema operacional, não é necessário importar se um programa do usuário grava em uma união ou em uma estrutura. Na verdade, isso é apenas uma questão do compilador.Outra propriedade importante de união e estrutura é que eles permitem que um ponteiro para eles possa apontar para tipos de qualquer um de seus membros . Portanto, o seguinte é válido:
some_test_pointer pode apontar para
int*
oudouble*
. Se você converter um endereço do tipotest
paraint*
, ele apontará para o primeiro membroa
, na verdade. O mesmo vale para uma união também. Portanto, como uma união sempre terá o alinhamento correto, você pode usar uma união para tornar válido apontar para algum tipo:Essa união será capaz de apontar para um int e um double:
é realmente válido, conforme declarado pelo padrão C99:
O compilador não otimizará o valor,
v->a = 10;
pois isso pode afetar o valor de*some_int_pointer
(e a função retornará em10
vez de5
).fonte
A
union
é útil em alguns cenários.union
pode ser uma ferramenta para manipulação de nível muito baixo, como escrever drivers de dispositivo para um kernel.Um exemplo disso é dissecar um
float
número usandounion
astruct
com campos de bits e afloat
. Eu guardo um número nofloat
e, posteriormente, posso acessar partes específicas dofloat
mesmostruct
. O exemplo mostra comounion
é usado para ter ângulos diferentes para examinar os dados.Dê uma olhada na descrição de precisão única na wikipedia. Eu usei o exemplo e o número mágico 0,15625 a partir daí.
union
também pode ser usado para implementar um tipo de dados algébrico que possui várias alternativas. Encontrei um exemplo disso no livro "Real World Haskell" de O'Sullivan, Stewart e Goerzen. Confira na seção A união discriminada .Felicidades!
fonte
" union " e " struct " são construções da linguagem C. Falar de uma diferença no "nível do sistema operacional" entre eles é inadequado, pois é o compilador que produz código diferente se você usar uma ou outra palavra-chave.
fonte
Não tecnicamente falando significa:
Suposição: cadeira = bloco de memória, pessoas = variável
Estrutura : Se houver 3 pessoas, elas poderão sentar-se na cadeira de seu tamanho correspondente.
União : Se houver 3 pessoas, apenas uma cadeira estará lá para sentar, todas precisam usar a mesma cadeira quando quiserem se sentar.
Tecnicamente falando significa:
O programa abaixo mencionado dá um mergulho profundo na estrutura e união.
Total MAIN_STRUCT size = sizeof (UINT64) para bufferaddr + sizeof (UNIT32) para união + 32 bits para preenchimento (depende da arquitetura do processador) = 128 bits. Para estrutura, todos os membros obtêm o bloco de memória contíguo.
Union obtém um bloco de memória do membro de tamanho máximo (aqui são 32 bits). Dentro da união, há mais uma estrutura (INNER_STRUCT), seus membros obtêm um bloco de memória de tamanho total de 32 bits (16 + 8 + 8). Em união, o membro INNER_STRUCT (32 bits) ou os dados (32 bits) podem ser acessados.
fonte
Sim, a principal diferença entre struct e union é a mesma que você afirmou. O Struct usa toda a memória de seu membro e o union usa o maior espaço de memória de membros.
Mas toda a diferença está na necessidade de uso da memória. O melhor uso da união pode ser visto nos processos do unix, onde fazemos uso de sinais. como um processo, pode agir apenas com um sinal de cada vez. Portanto, a declaração geral será:
Nesse caso, o processo utiliza apenas a memória mais alta de todos os sinais. mas se você usar struct nesse caso, o uso da memória será a soma de todos os sinais. Faz muita diferença.
Para resumir, o Union deve ser selecionado se você souber que acessa qualquer membro de cada vez.
fonte
Você tem isso, é tudo. Mas então, basicamente, qual é o sentido dos sindicatos?
Você pode colocar no mesmo local o conteúdo de tipos diferentes. Você precisa saber o tipo do que armazenou na união (tantas vezes você o coloca em um
struct
com uma tag de tipo ...).Por que isso é importante? Não é realmente para ganhos de espaço. Sim, você pode ganhar alguns bits ou fazer algum preenchimento, mas esse não é mais o ponto principal.
É para segurança de tipos, permite que você faça algum tipo de 'digitação dinâmica': o compilador sabe que seu conteúdo pode ter significados diferentes e o significado preciso de como sua interpretação depende de você em tempo de execução. Se você tem um ponteiro que pode apontar para tipos diferentes, você DEVE usar uma união, caso contrário, seu código pode estar incorreto devido a problemas de alias (o compilador diz para si mesmo "oh, apenas esse ponteiro pode apontar para esse tipo, para que eu possa otimizar fora esses acessos ... ", e coisas ruins podem acontecer).
fonte
Uma estrutura aloca o tamanho total de todos os elementos nela.
Uma união aloca apenas a quantidade de memória que o maior membro exige.
fonte
qual é a diferença entre estrutura e união?
A resposta curta é: A deferência está na alocação de memória. Explicação: Na estrutura, o espaço de memória será criado para todos os membros dentro da estrutura. Na união, o espaço de memória será criado apenas para um membro que precise de maior espaço de memória. Considere o seguinte código:
Aqui existem dois membros dentro de struct e union: int e long int. O espaço de memória para int é: 4 bytes e o espaço de memória para int longo é: 8 no sistema operacional de 32 bits.
Portanto, para struct 4 + 8 = 12 bytes serão criados, enquanto 8 bytes serão criados para união
Exemplo de código:
Ref: http://www.codingpractise.com/home/c-programming/structure-and-union/
fonte
Os usos das uniões sindicais são usados com freqüência quando são necessárias conversas especializadas do tipo. Para se ter uma idéia da utilidade da união. A biblioteca padrão c / c não define nenhuma função projetada especificamente para gravar números inteiros curtos em um arquivo. O uso de fwrite () incorre em sobrecarga excessiva para operação simples. No entanto, usando uma união, você pode criar facilmente uma função que grava o binário de um número inteiro curto em um arquivo, um byte por vez. Suponho que inteiros curtos tenham 2 bytes de comprimento
O EXEMPLO:
embora putw () chamei com número inteiro curto, era possível usar putc () e fwrite (). Mas eu queria mostrar um exemplo para dominar como uma união pode ser usada
fonte
estrutura é uma coleção de tipos de dados diferentes, onde diferentes tipos de dados podem residir nela e cada um obtém seu próprio bloco de memória
geralmente usamos união quando temos certeza de que apenas uma das variáveis será usada de uma só vez e você deseja utilizar totalmente a memória presente, porque ela obtém apenas um bloco de memória que é igual ao maior tipo.
memória total que obtém => 5 bytes
memória total que obtém = 4 bytes
fonte
As uniões são úteis ao escrever uma função de ordenação de bytes, que é fornecida abaixo. Não é possível com estruturas.
fonte
Uma União é diferente de uma estrutura, uma vez que uma União se repete sobre as outras: ela redefine a mesma memória enquanto a estrutura define uma após a outra sem sobreposições ou redefinições.
fonte