Obra: Programar em C/Tipos de dados definidos pelo usuário
tipos de dados definidos pelo usuário muitas vezes necessário manipular dados complexos que seriam difíceis de representar usando apenas os tipos primitivos char int double float para isso há em três tipos de dados que podem ser definidos pelo usuário estruturas struct uniões union enumerações enum as estruturas uniões são compostas por várias variáveis escolhidas pelo programador por isso são ditos definidos pelo usuário já as enumerações são resumidamente tipos cujos valores devem pertencer um conjunto definido pelo programador estruturas uma estrutura ou struct um tipo de dados resultante do agrupamento de várias variáveis nomeadas não necessariamente similares numa só essas variáveis são chamadas membros da estrutura para declarar uma estrutura usamos palavra chave struct seguida do nome que se deseja dar estrutura ao tipo de dados de um bloco contendo as declarações dos membros veja um exemplo struct mystruct int double char string este exemplo cria um tipo de dados denominado mystruct contendo sete membros string note que nome mystruct nome do tipo de dados não de uma variável desse tipo um exemplo simples de aplicação de estruturas seria uma ficha pessoal que tenha nome telefone endereço ficha seria uma estrutura ou mais amplamente uma estrutura seria uma representação de qualquer tipo de dado definido por mais de uma variável por exemplo tipo file na verdade um ponteiro para uma estrutura que contém alguns dados que sistema usa para controlar acesso ao fluxo arquivo não necessário para maioria dos programadores conhecer estrutura do tipo file definindo tipo definição de um tipo de estrutura feita com palavra chave struct seguida do nome ser dado ao tipo de um bloco contendo as declarações dos elementos da estrutura struct nome_do_tipo tipo_elem tipo_elem muito importante incluir ponto vírgula ao final do bloco declarando para declarar uma variável de um tipo já definido fornecemos nome do tipo incluindo palavra chave struct struct nome_do_tipo variavel também possível condensar definição do tipo declaração em um passo substituindo nome do tipo pela definição sem ponto vírgula struct mystruct int double char string variavel também possível inicializar uma estrutura usando as chaves para envolver os elementos da estrutura separados por vírgulas os elementos devem estar na ordem em que foram declarados mas não obrigatório inicializar todos no entanto para inicializar um elemento todos os anteriores devem ser inicializados também por exemplo poderíamos declarar valores iniciais para variável acima da seguinte maneira struct mystruct variavel teste struct mystruct inicializador designado para quem usa com compilador gnu durante inicialização de um estrutura possível especificar nome do campo com nome_do_campo antes do valor exemplo struct mystruct acessando para acessar modificar os membros de uma estrutura usamos operador de seleção ponto esquerda do ponto deve estar nome da variável estrutura direita nome do membro podemos usar os membros co
rda do ponto deve estar nome da variável estrutura direita nome do membro podemos usar os membros como variáveis normais inclusive passando os para funções como argumentos variavel variavel strcpy variavel string bom dia printf variavel variavel variavel string vetores de estruturas sendo as estruturas como qualquer outro tipo de dados podemos criar vetores de estruturas por exemplo suponha algum programa que funcione como um servidor permita até usuários conectados simultaneamente poderíamos guardar as informações desses usuários num vetor de estruturas struct info_usuario int id char nome long endereco_ip time_t hora_conexao struct info_usuario usuarios por exemplo para obter horário em que usuário usuário se conectou poderíamos escrever usuarios hora_conexao atribuição cópia podemos facilmente copiar todos os campos de uma estrutura para outra fazendo uma atribuição simples como de inteiros struct ponto int int struct ponto struct ponto agora ponto também tem coordenadas no entanto devemos ter cuidado se estrutura contiver campos ponteiros pois nesses casos que será copiado endereço de memória não conteúdo daquele endereço por exemplo se tivermos uma estrutura que comporta um inteiro uma string uma cópia sua conterá mesmo inteiro um ponteiro para mesma string que significa que alterações na string da cópia serão refletidas também no original passando para funções já vimos acima que podemos normalmente passar membros de uma estrutura como argumentos de funções também possível passar estruturas inteiras como argumentos include struct ponto int int void imprime_ponto struct ponto printf int main struct ponto imprime_ponto return no entanto há dois possíveis problemas nisso alterações nos membros da estrutura só terão efeito dentro da função chamada mas não na função que chamou isso ocorre pois estrutura passada por valor não por referência quando estrutura contiver muitos elementos passagem por valor tornar se um processo de cópia de muitos dados por isso de costume passar estruturas por referência como ponteiros mesmo que estrutura em questão seja pequena uniões uniões são parecidas com estruturas mas há uma diferença fundamental nas uniões todos os elementos ocupam mesmo espaço de memória por isso só possível acessar um elemento por vez já que uma mudança em um elemento causará mudança em todos os outros definição declaração de uniões igual das estruturas trocando palavra struct por union há principalmente dois usos para as uniões economia de espaço já que guardam se várias variáveis no mesmo espaço representação de uma informação de mais de uma maneira um exemplo disso são os endereços ip que na biblioteca de sockets podem ser representados como um grupo de octetos char ou como um único valor inteiro int isso feito com uma união parecida com esta union ip_address int s_long char s_byte dessa maneira endereço pode ser facilmente representado de maneira humanamente legível com octetos sem dificultar processamento interno com valor inteiro enumer
aneira humanamente legível com octetos sem dificultar processamento interno com valor inteiro enumerações enumeração enum ou tipo enumerado um tipo de dados que tem como conjunto de valores possíveis um conjunto finito de identificadores nomes determinados pelo programador em cada identificador em uma enumeração corresponde um inteiro enumerações são definidas de maneira similar às estruturas uniões com algumas diferenças palavra chave usada enum enum nome_enumeração identificador_ identificador_ identificador_n note as diferenças não há ponto vírgula no final ou no meio das declarações mas ainda há no final do bloco não há declaração de tipos com essa declaração ao identificador_ será atribuido valor ao identificador_ será atribuído valor assim por diante podemos também explicitar os valores que quisermos colocando um sinal de igual valor desejado após identificador caso não haja valor determinado para primeiro identificador ele será zero para os demais identificadores padrão seguir ordem dos números partir do valor do identificador anterior podemos misturar identificadores de valor determinado com identificadores de valor implícito bastando seguir regra acima por exemplo enum cores vermelho azul verde amarelo marrom uso da mesma maneira que criamos uma variável de um tipo struct ou union podemos criar variáveis de um tipo enumerado enum enum cores cor_fundo para atribuir valores uma variável enumerada podemos usar como valor tanto identificador quanto valor correspondente seriam equivalentes portanto cor_fundo verde cor_fundo na verdade variáveis enumeradas agem de maneira quase igual aos inteiros possível assim atribuir valores que não correspondem nenhum dos identificadores campo de bits na linguagem campo de bits bitfields uma estrutura um pouco estranha em vez de usar variáveis com tipos diferentes os campos são formados com as partes de um inteiro tamanho de um campo de bits não pode ser maior que tipo usado aqui um short typedef struct unsigned short campo_ tamanho bit campo_ campo_ campo_ campo_ bit_field_ essa estrutura esta formada por um tipo que tem tamanho de um short esse mesmo tipo será divido em porções menores no exemplo acima os campos tem os tamanhos igual bits que tamanho de um unsigned short para acessar os campos usamos mesmo método que usamos com estruturas normais bit_field_ meu_campo meu_campo campo_ meu_campo campo_