Ir para conteúdo
Fórum Script Brasil
  • 0

[DÚVIDA] Struct aninhada em union


qisdo

Pergunta

Olá, estou com uma dúvida referente a saída deste código:

#include <stdio.h>
#include <stdlib.h>

typedef union { //uniao compartilha os dados
	char A[2];
	struct xar //para acessar nome_da_variavel_da_estrutura.nome_do_elemento
	//Quando uma variável de estrutura é declarada, o compilador C aloca automaticamente memória suficiente para acomodar todos os seus membros.
	{
		char B; //elemento da estrutura
		char C;
	}carac; // nome da variavel da estrutura
} PosCompType;

int main() 
{
	PosCompType Dado;
	Dado.A[0] = 'a';
	Dado.A[1] = 'b';
	Dado.carac.B = 'c';
	Dado.carac.C = 'd';
	printf("%c %c %c %c\n", Dado.A[0], Dado.A[1], Dado.carac.B, Dado.carac.C);
	return 0;
}

No console o resultado do printf não deveria ser abcd?

Por que esta saindo cdcd? Será que é pelo fato de a união compartilhar memória?

Troquei a ordem para:

        Dado.carac.B = 'c';
	Dado.carac.C = 'd';
        Dado.A[0] = 'a';
	Dado.A[1] = 'b'; 

E o resultado sai abab, indiciando que os últimos valores corrompem os primeiros.

Alguma explicação?

Editado por qisdo
Link para o comentário
Compartilhar em outros sites

3 respostass a esta questão

Posts Recomendados

  • 0

Isso é por que você acha que ele está reservado na memoria assim:

+-----+-----+-----+-----+
|Byte0|Byte1|Byte2|Byte3|
+-----+-----+-----+-----+
| a[0]| a[1]|  B  |  C  |
+-----+-----+-----+-----+

Más na realidade ele esta assim:

+-----+-----+
|Byte0|Byte1|
+-----+-----+
| a[0]| a[1]|
+-----+-----+
|  B  |  C  |
+-----+-----+

O dato B compartilha memoria com o dado a[0], e o dado C com A[1]. Supondo que todos ocupam 1Byte em memoria.

Como disse no coment do seu programa: "eles compartilham memoria". Más a pega é que você não pode usar ele para duas coisas ao mesmo tempo.

Para que você entenda melhor imaginamos que temos a seguinte união:

union unEjemplo {
int A;  //4Bytes
char B; //1Byte
float C;//8Bytes
} UnionEjemplo;

Então vamos tomar que em um determinado computador um int ocupa 4Bytes, um char ocupa 1Byte e um float ocupa 8Bytes(Esses podem variar de tamanho dependendo de fatores como compilador, SO etc). Em uma estrutura normal ele estaria representado em memoria de esta forma:

+------+------+------+------+------+------+------+------+------+------+------+------+------+
|Byte00|Byte01|Byte02|Byte03|Byte04|Byte05|Byte06|Byte07|Byte08|Byte09|Byte10|Byte11|Byte12|
+------+------+------+------+------+------+------+------+------+------+------+------+------+
|             A             |   B  |                           C                           |
+------+------+------+------+------+------+------+------+------+------+------+------+------+

...Ocupando a soma de todos seus membros int tamanhoEstructura = sizeof(A)+sizeof©+sizeof© //Depende também do alinhamento de Bytes ou em inglês Byte Align(Buscar en google).

Más em uma união eles seriam assim:

+------+------+------+------+------+------+------+------+
|Byte00|Byte01|Byte02|Byte03|Byte04|Byte05|Byte06|Byte07|
+------+------+------+------+------+------+------+------+
|             A             |
+------+------+------+------+
|  B   |    
+------+------+------+------+------+------+------+------+
|                           C                           |
+------+------+------+------+------+------+------+------+

int tamanhoUnion = sizeof©; //C é o tipo de dado de maior tamanho de todos nesse exemplo, por isso a união vai levar o tamanho dele e todos os dados vão compartilhar essa mesma memoria.

O Byte 0 do charB estaria compartilhando do Byte 0 de intA(ocupariam a mesma memoria) e vice versa. Os Bytes 0,1,2 e 3 de floatC compartilham o mesmo espaço que o Byte 0,1,2 e 3 de intA e vice versa. Todos os Bytes 0 dos membros compartilham o mesmo espaço.

Acho que da para entender.

Então... no seu exemplo:

+-----+-----+
|byte0|byte1|
+-----+-----+
| a[0]| a[1]|
+-----+-----+
|  B  |  C  |
+-----+-----+

Me permita fazer uma analogia: Os dados A[0],A[1],B e C vamos pensar que eles são carros, e que seus nomes são marcas ou modelos. Eles são carros muito evoluídos, são quase mágicos, pois eles possuem uma característica que nenhum carro convencional tem. Seu porta malas! Esse porta malas ocupa o mesmo espaço tempo(memoria) que do seus parceiros do tamanho de 1Byte =D.

Por exemplo: o carro A[0] comparte um porta-malas do tamanho de 1Byte com seu parceiro carro B, se eu puser qualquer coisa que ocupa um Byte em qualquer dos porta malas de um de esses 2 carros, automaticamente o outro vai ter o mesmo conteudo no seu porta malas. kkkk

Si eu puser um caractere 'x' no porta malas de A[0], B também vai ter ese 'x' no seu porta malas. Capiche?

Os carros A[0] e B compartilham esse revolucionário porta malas entre si, e A[1] e C também.

Ok feita a analogia o que aconteceu foi que você colocou no porta malas dos carros B(que compartilha com A[0]) e C(que compartilha com A[1])os dados 'c' e 'd'. Então si B='c' e C='d' os porta malas de ficam A[0]='c' e A[1]='d'.

Em linguagem de programação fica ((B='c') == (A[0]='c')) e ((C='d')== (A[1]='d')) Por que compartilham memoria.

As uniões já não são amplamente utilizadas por que se criaram para computadores que continham pouca memoria RAM já que como podemos ver "compartilham" a mesma memoria RAM, más seu uso é muito complexo e pouco recomendado em entornos de trabalhos atuais dado que qualquer maquina hoje em dia tem ao menos 2gigas ou más de RAM. Más aprender sobre unioes te pode ajudar em muitas coisas como por exemplo sockts que usam algumas uniões algo complicadas para estabelecer comunicação entre 2 ou más computadores.

Si você quiser um conselho não esta de mais você aprender uniões, más eu não perderia demasiado tempo com elas já que pouco uso vão ter nos dias que correm atualmente. XD

Sorte: :lol:

Link para o comentário
Compartilhar em outros sites

  • 0

Pois então, tenho áreas de estudo em microcontroladores onde a memória é limitada e o uso de uniões pode ser interessante.

Para o computador realmente não se faz necessário, mas como bom programador é sempre bom conhecer todos os recursos. Na bibliografia encontrei a explicação do compartilhamento de memória e parei ali, porque ainda não tinha caído a ficha. :)

Obrigado pela dica, parabéns pelo texto e exemplos, que sinceramente, foi muito útil para o entendimento.
Abraço.

Link para o comentário
Compartilhar em outros sites

Participe da discussão

Você pode postar agora e se registrar depois. Se você já tem uma conta, acesse agora para postar com sua conta.

Visitante
Responder esta pergunta...

×   Você colou conteúdo com formatação.   Remover formatação

  Apenas 75 emoticons são permitidos.

×   Seu link foi incorporado automaticamente.   Exibir como um link em vez disso

×   Seu conteúdo anterior foi restaurado.   Limpar Editor

×   Você não pode colar imagens diretamente. Carregar ou inserir imagens do URL.



  • Estatísticas dos Fóruns

    • Tópicos
      152,3k
    • Posts
      652,3k
×
×
  • Criar Novo...