• Nenhum resultado encontrado

union [<union-type-name>] { <type> <variable-names> ;... } [<union-variables>] ; union int_or_long { int i; long l; } a_number;

N/A
N/A
Protected

Academic year: 2021

Share "union [<union-type-name>] { <type> <variable-names> ;... } [<union-variables>] ; union int_or_long { int i; long l; } a_number;"

Copied!
8
0
0

Texto

(1)

Uniões

Uma união (union) consiste de uma variável que pode conter valores de diferentes tipos compartilhando a mesma área de memória.

Uma união é semelhante a uma struct, exceto que ela permite definir variáveis que compartilham o mesmo espaço de armazenamento.

Formato:

Por exemplo,

O compilador alocará memória suficiente para acomodar o elemento maior na união.

Ao contrário da struct, as variáveis a_number.i e a_number.l ocupam a mesma localização em memória. Assim, escrevendo em uma irá escrever sobre o valor da outra.

Acessos aos elementos de uma união são feitos da mesma maneira como em uma struct. Exemplo:

O grupo de campos x, y, z compartilha a mesma área de memória do grupo r, theta, phi, assim, como x e r compartilham a mesma área de memória, se o valor de x for alterado o valor de r também será alterado. O mesmo acontece com y e theta, z e phi.

O número de bytes que uma struct (registro) ocupa na memória é a soma dos tamanhos dos seus campos. Se a struct contém uma union, a área ocupada de memória é o tamanho necessário para comportar os maiores campos das unions que compoem a struct.

Definições de Tipos

Formato:

typedef <type-definition> <identifier> ;

Associa um nome novo de tipo <identifier> a um tipo <type-definition>.

struct Ponto { bool polar; union { struct { float x, y, z; }; struct {

float r, theta, phi; }; }; }; union [<union-type-name>] { <type> <variable-names> ; ... } [<union-variables>] ; union int_or_long { int i; long l; } a_number;

(2)

Exemplos:

Iniciação de Variáveis Complexas

Iniciação com Tipos Simples

Exemplo:

int maximo = 9999; float fator = -0.1; char breakchar = 3;

Iniciação em Arrays

O número de elementos pode ou não ser explicitado, uma vez o sendo, os dados de iniciação serão colocados nos primeiros elementos do vetor.

Exemplo com reais:

float vetX[] = {1.2, 3.4, 5.6, 7.8, 9.0};

um vetor com 5 elementos será criado e iniciado com os valores especificados. Cadeia de Caracteres:

char str[] = "Teste de iniciacao";

Vetor de Caracteres:

char vetChar[] = {'a', 'e', 'i', 'o', 'u'};

Vetor de Cadeia de Caracteres:

char *descrEstado[3] = {"Ativo", "Passivo", "Esperando"};

um vetor com 3 elementos ponteiros indicando as cadeias especificadas será criado a utilização do vetor é normal, por exemplo, para apresentar um elemento do vetor na tela, usamos:

printf("%s\n", descrEstado[1]);

Array Multidimensional:

int vetor[2][2] = {{1, 2}, {3, 4}};

Inicia vetor com os valores:

vetor[0][0] = 1 vetor[0][1] = 2 vetor[1][0] = 3 vetor[1][1] = 4

Iniciação em structs

Exemplos:

enum Mes {JAN, FEV, MAR, ABR, MAI, JUN, JUL, AGO, SET, OUT, NOV, DEZ}; struct Data {

int dia; Mes mes; int ano; };

Data dataNascimento = {11, DEZ, 1913};

typedef int INTEGER; /* criação do tipo INTEGER */ INTEGER var2; /* utilização do tipo */

typedef struct { int dia, mes, ano; } tipoData;

(3)

struct Point { float x, y; };

Point caminho[3] = {{1.2, 3.4}, {5.6, 7.8}, {9.0, 1.2}};

Iniciação com Ponteiros

Exemplo:

enum Direcao {ESQ, DIR, ACIMA, ABAIXO}; typedef char * string;

struct No {

struct No * prox; string simbolo; enum Direcao valor; };

struct No N1 = {NULL, "Abaixo", ABAIXO}; struct No N2 = {&N1, "Acima", ACIMA}; struct No N3 = {&N2, "Direita", DIR}; struct No N4 = {&N3, "Esquerda", ESQ}; struct No * listaDirecoes = &N4;

int main() { printf("%s -> ", listaDirecoes->simbolo); printf("%s -> ", listaDirecoes->prox->simbolo); printf("%s -> ", listaDirecoes->prox->prox->simbolo); printf("%s\n", listaDirecoes->prox->prox->prox->simbolo); getchar(); }

Parâmetros para a Função main

Pode-se usar dois argumentos na função main(). Esses argumentos são atribuídos pelo sistema operacional no momento da iniciação do programa. O primeiro argumento é um inteiro que contém o número de elementos (cadeias de caracteres) recebidos do S.O. O segundo argumento é um vetor de ponteiros para as cadeias de caracteres recebidas.

Operações com Arquivos

Funções com protótipos no arquivo de cabeçalhos “stdio.h”.

Função fopen()

Abre um arquivo

FILE *fopen(const char *filename, const char *mode);

fopen abre o arquivo com o nome filename e retorna um ponteiro para uma estrutura de informações do arquivo aberto. Se o ponteiro é NULL, indica erro de abertura.

#include <stdio.h>

void main(int argc, char *argv[]) {

printf(“Exite(m) %d parâmetros\n”, argc); if (argc!=2)

printf(“%s\n”, “Número inválido de parâmetros\n”); else

printf(“%s %s\n”, “Parâmetro:”, argv[1]); }

(4)

A cadeia de caracteres mode indica o modo de abertura do arquivo.

Função fclose()

Fecha um arquivo.

int fclose(FILE *stream);

Grava no disco todas informações associadas ao arquivo antes de fechá-lo. Retorna zero no sucesso ou EOF se um erro for detectado.

Função fgetc()

int fgetc(FILE *stream);

Retorna o caracter atual do arquivo e avança o indicador para o próximo caracter ou EOF para indicar fim de arquivo.

Função fputc()

int fputc(int c, FILE *stream);

Escreve o caracter c no arquivo.

Função feof()

int feof(FILE *stream);

Retorna 1 para indicar fim do arquivo ou 0 caso contrário. modo descrição

r abre para leitura w abre para escrita

a abre para escrita no fim do arquivo + leitura/escrita

b arquivo binário t arquivo texto (default)

(5)

Exemplo:

Macros putc() e getc()

A macros putc() e getc() são compatíveis às funções fputc() e fgetc(), respectivamente. Existem por motivos de compatibilidade.

Arquivos Padrões

Arquivos definidos automaticamente abertos quando o programa é iniciado. Esses arquivos são:

Esses arquivos estão declarados no stdio.h.

Ponteiros

As variáveis podem ser de três tipos:

1. variáveis estáticas - estão ocupando espaço de memória durante a execução do programa, existem enquanto o programa existe;

2. variáveis temporárias - são declaradas nas áreas subrotinas (procedimento ou função), são as variáveis locais;

3. variáveis dinâmicas - tem espaço de memória alocado para a variável quando ela se torna necessária e quando não serão mais utilizadas a memória pode ser liberada. A alocação e a liberação de memória deve ser explicitada pelo programador.

#include <stdio.h> void main() { char ch;

FILE *fpEnt, *fpSai;

char arqEnt[80], arqSai[80]; printf("Arquivo de entrada: "); gets(arqEnt);

if (!(fpEnt=fopen(arqEnt, "rb"))) {

printf("Erro na abertura do arquivo %s\n", arqEnt); return;

}

printf("Arquivo de saida: "); gets(arqSai);

if (!(fpSai=fopen(arqSai, "wb"))) {

printf("Erro na abertura do arquivo %s\n", arqSai); return; } while (!feof(fpEnt)) { ch=fgetc(fpEnt); fputc(ch, fpSai); if (ch==' ') { while ((ch=fgetc(fpEnt))==' '); fputc(ch, fpSai); } } fclose(fpSai); fclose(fpEnt); }

stdin dispositivo de entrada padrão (teclado) stdout dispositivo de saída padrão (vídeo)

stderr dispositivo de saída padrão de erros (vídeo) stdaux dispositivo auxiliar padrão

(6)

As variáveis dinâmicas são áreas de memória parcialmente gerenciadas de forma automática pelo programa. Para que estas áreas não se percam, elas devem constantemente ser referenciadas por uma variável do tipo ponteiro, ou seja, sempre devem existir ponteiros mantendo os endereços das variáveis dinâmicas.

Ponteiros são variáveis que armazenam endereços de elementos na memória. Existem duas formas de declarar ponteiros:

1. Ponteiro genérico, aponta para uma posição genérica (sem tipo) de memória: void * ptr;

2. Ponteiro com tipo, aponta para uma posição que supostamente tem uma variável de um determinado tipo:

int *pInt;

Note que o asterisco após do tipo int, indica que a variável declarada é um ponteiro para o tipo inteiro.

Um ponteiro com tipo indica uma área de memória que supostamente contém um valor com o tipo indicado. Se for necessário manipular o conteúdo dessa área, então utilizamos novamente o asterisco antes do nome da variável:

Exemplo: typedef int * pInt; int i; pInt: p; int main() { i=100;

p=pInt(100); // o valor do inteiro armazenado na posição printf("%d, %d", i, *p); // 100 será apresentado no vídeo

. . .

Observe a variável i no programa acima, ela contém o número 100. A variável p representa o endereço de um inteiro (100 é o endereço) e *p representa o valor (inteiro) encontrado na posição 100 da memória. O programa acima encontrará problemas de execução, pois o acesso ao endereço 100 não é uma região de memória onde o programa tem acesso permitido.

Experimente o programa em um compilador de 16 bits (TC++ 1.1 por exemplo):

#include <stdio.h> long int far * pClock; void main() {

pClock = (long int far *)0x46c; do {

printf("%ld\n", *pClock); } while (1);

}

Note: o endeço $46c é um inteiro longo (4 bytes) que mantém o número de tics do relógio desde a hora zero até o instante atual. Cada tic ocorre 18,21 vezes por segundo.

100 100

(7)

Exemplo: typedef int * pInt; int i; pInt: p; int main() { i=100; p=&i; printf("%d, %d", i, *p); . . .

No vídeo serão impressos o valor de i (100) e o valor contido na posição de memória apontada por p (100), isso porque p aponta para i. Assim uma atribuição *p=50, tem o mesmo efeito de i=50. Os ponteiros e as variáveis dinâmicas podem ser representados graficamente por caixas. A seta que sai de um ponteiro representa que o endereço contido naquele ponteiro.

Utilizar ponteiros indicando conteúdo de variáveis não dinâmicas não tem sentido. Para que os ponteiros tenham sentido é necessário que a memória indicada seja alocada apenas quando for necessária.

A alocação é feita pela rotina malloc. A liberação pela free. Exemplo: typedef float *pReal; pReal p; int main() { p = (pReal)malloc(sizeof(float)); *p = 123.45; printf("%f\n", *p); free(p); end.

Antes da malloc ser chamada, p era um ponteiro com sujeira (o endereço que ele continha não apontava para nada útil).

A chamada à função malloc(), aloca (reserva) uma área de memória capaz de manter um float, e o ponteiro p recebe o endereço desta área. A área de memória alocada é chamada de variável dinâmica. O parâmetro do malloc indica o número de bytes de memória a serem alocados. A forma mais fácil para calcular número de bytes a serem alocados é usar o operador sizeof, no exemplo, sizeof(float) retorna 4 (um float ocupa 4 bytes). O cast (pReal) ou (float *) transforma o ponteiro void * (tipo retornado pelo malloc) em float *.

A manipulação da área de memória é feita através de *p. A atribuição

*

p=123.45 coloca o real 123.45 na variável dinâmica.

Quando a variável dinâmica não for mais necessária, chamamos a rotina free(p) que libera a área de memória alocada. endereço de i 100 p i p real p 123.45 p

(8)

Algumas vezes é necessário identificar se um ponteiro indica ou não uma variável dinâmica válida. Para isso podemos sempre atribuir o valor NULL para ponteiros não utilizados. As representações mais usuais para um ponteiro com NULL são:

O mais comum em ponteiros é utilizar uma struct onde um ou mais campos são também ponteiros. Isso permite a criação de relacionamentos complexos entres vários registros.

Exemplo:

typedef

char tInfo; // ou outro tipo qualquer

typedef struct sreg { tinfo dado;

struct sreg P1, P2; } reg;

Typedef struct sreg * pReg; pReg PrimPtr; int main() { PrimPtr = (pReg)malloc(sizeof(reg)); PrimPtr->dado = 'X'; PrimPtr->P2 = (pReg)malloc(sizeof(reg)); PrimPtr->P2->dado = 'Y'; PrimPtr->P2->P1 = NULL; PrimPtr->P2->P2 = NULL; PrimPtr->P1 = (pReg)malloc(sizeof(reg)); PrimPtr->P1->dado = 'Z; PrimPtr->P1->P1 = PrimPtr->P2; PrimPtr->P1->P2 = PrimPtr; . . .

p p X Y Z PrimPtr

Referências

Documentos relacionados

Os Chefes de Estado e de Governo concordaram em criar um Comité Africano de Alto Nível para o Comércio (HATC), composto pelos actuais Presidentes das CERs

Gestão de Capital é definida como: i) Monitoramento e controle do capital mantido pela instituição ii) Avaliação da necessidade de capital para fazer face aos riscos a que a

Os Chefes de Estado e de Governo concordaram em criar um Comité Africano de Alto Nível para o Comércio (HATC), composto pelos actuais Presidentes das CERs

Dentre os estágios identificados pelos autores, o primeiro passo já foi trabalhado pela seção 4.1, na qual foram apresentados os dados que compõem o corpus da pesquisa, juntamente

Considerando ainda as questões em cursos, novas e emergentes como sendo: (1) Estatísticas das receitas; (2) Roteiro para o Desenvolvimento de Sistemas de Informação do

Iniciada pelos eleitos e pelas autoridades regionais fronteiriças, essa experiência deu lugar à criação da Associação das Regiões Fronteiriças da Europa (AFRE) bem como ao

Full name/Name State Unitary Enterprise of the “Republic of Crimea”“Production- Agrarian Union ‘Massandra’”.

Além do canal 0800, o cliente pode registrar sua demanda também via RDR – Banco Central, email e formulário de atendimento, disponível no Site da Corretora Western