Buscar

Apostila ICC

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 3, do total de 35 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 6, do total de 35 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 9, do total de 35 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Prévia do material em texto

1 
INTRODUÇÃO À CIÊNCIA DA COMPUTAÇÃO 
André Christóvão Pio Martins - DEE 
 
OBJETIVOS 
Ao término da disciplina o aluno deverá ser capaz de construir algoritmos para solução de 
problemas de média complexidade e implementá-los em linguagem C 
 
CONTEÚDO 
1. Características básicas dos computadores 
2. Algoritmos e programas 
3. Linguagem de baixo e de alto nível 
4. Linguagens compiladas e interpretadas 
5. Programação procedural e orientada a objetos 
6. Linguagem C: 
a. Estrutura da linguagem 
b. Tipos de dados e declarações 
c. Operadores, comandos de atribuição, entrada e saída 
d. Funções pré-definidas 
e. Estruturas de seleção e repetição 
f. Vetores, Matrizes e Strings 
g. Arquivos 
h. Funções e subrotinas 
 
BIBLIOGRAFIA BÁSICA 
1. ASCENCIO & CAMPOS: Fundamentos da Programação de Computadores - Algoritmos, 
Pascal, C/C++ e Java. Pearson. 
2. JOYANES: Fundamentos de Programação: Algoritimos, Estruturas de Dados e Objetos. 
McGraw-Hill. 
3. SCHILDT: C Completo e Total. Pearson. 
4. ALVES. C++ Builder 6. Érica. 
5. FORBELLONE & EBERSPACHER: Lógica de Programação - A Construção de 
Algoritmos e Estruturas de Dados. Makron Books. 
6. SALIBA: Técnicas de Programação – Uma Abordagem Estruturada. Makron Books. 
7. Apostilas da Internet (UFMG, UNICAMP, etc) 
 
CRITÉRIO DE AVALIAÇÃO 
0,5
2
21 ≥+= PPMP 
 
Obs 1. Presença obrigatória (70%) 
 2. O material das aulas será enviado por e-mail 
 3. O material referente a cada aula deve ser lido antes da aula 
 4. Compilador CodeBlocks 
5. Compilador DevC++ 
 2 
CARACTERÍSTICAS BÁSICAS DOS COMPUTADORES DIGITAIS 
 
 
1- Monitor 2- Placa-mãe 3- Processador 
4- Memória RAM 5- Placas de rede, som,... 6- Fonte de energia 
7- Leitor de CD/DVD 8- Disco rígido(HD) 9- Mouse 
10- Teclado 
 
HARDWARE: parte física do computador, o principal componente é a CPU 
(CPU≠gabinete), os demais são dispositivos de entrada e saída. 
 
SOFTWARE: parte lógica do computador, são os programas: 
• Sistema Operacional: gerencia o hardware, os demais programas e o uso do 
hardware pelos programas, é uma plataforma para os aplicativos. 
• Compilador: permite a construção de novos aplicativos (DevC++, TurboPascal, etc.). 
• Aplicativo: programa que executa tarefas específicas e pré-definidas (Word: edição 
de texto, PowerPoint: apresentação, MatLab: cálculos matemáticos, etc). 
 
Obs: os detalhes do uso do hardware pelos programas que serão implementados não 
serão abordados. 
 
No hardware você bate, o software você xinga. 
 
 3 
 
UC – Unidade de Controle 
ULA – Unidade Lógica e Aritmética 
DMA – Acesso Direto à Memória 
UCP – Unidade Central de Processamento 
 (Microprocessador/Microcontrolador ≠ CPU/Gabinete) 
 
MEMÓRIA 
 
Voláteis: registradores, cache, RAM 
Não-voláteis: ROM, HD, CD, DVD, memória flash 
 
DISPOSITIVOS DE E/S 
 
Teclado (E) Monitor de vídeo (S) Impressoras (S) 
Pen Drive (E/S) Disco Rígido (E/S) Discos Flexíveis (E/S) 
 
PROCESSAMENTO DA INFORMAÇÂO 
 
Os microprocessadores são formados por milhões de chaves (transistor) que podem estar 
abertas ou fechadas, ou seja, são capazes de distinguir apenas dois níveis de tensão (~3 
V, valor binário 1, e ~0 V, valor binário 0). 
 
A lógica que permite aos computadores digitais processar informação baseada nestes dois 
valores é chamada Álgebra de Boole. Portanto, toda informação (dados ou instruções) 
tratada pelos computadores digitais tem que ser convertida em BIT (BInary DigiT, 0 ou 1) 
ou BYTE (grupo de 8 bits). Como 28=256, em um byte podem-se representar 256 
diferentes valores, desde 0000.0000 até 1111.1111 ⇒ Linguagem de Máquina. 
 
Para que o computador seja funcional, as instruções e os dados devem ser arranjados de 
forma a que se atinjam objetivos específicos ⇒ Programas. 
 
A linguagem de máquina resulta em programas ininteligíveis e mesmo a Linguagem 
Assembly gera programas extensos, difíceis de serem entendidos, com baixa portabilidade 
e caros, embora eficientes e rápidos (linguagens de baixo nível). Por exemplo, para o 
microprocessador 8085 temos: 
 4 
 
Linguagem de máquina: 0011.1110 
0011.0010 
Linguagem Assembly: MVI A,32H 
Linguagem humana: Armazene o número 50 no Registrador A 
 
Alguns programas (compiladores) permitem que se escrevam os programas com 
instruções mais próximas da linguagem humana e fazem a tradução de tais programas 
para a linguagem de máquina. Linguagem de alto nível: ADA, ALGOL, BASIC, CLIPPER, 
COBOL, FORTRAN, LISP, LOGO, PASCAL, C, C++, Java, etc. 
 
Os programas podem ser executados à medida que as instruções são digitadas pelo 
programador (linguagens interpretadas), ou de uma só vez após o programa todo ter sido 
digitado, compilado e criado o arquivo executável (linguagens compiladas). No primeiro 
caso, o programa interpretador deve estar instalado na máquina. No segundo caso, basta 
que o executável criado esteja na máquina. 
 
Programação Estruturada: programas que usam estruturas de controle para definir a 
seqüência de execução das instruções (comandos IF, FOR, WHILE, REPEAT, etc). Evita a 
necessidade de LABEL e o comando GO TO. 
 
Programação Procedural: os programas são seqüências de chamadas de procedimentos, 
que podem alterar dados ou apenas executar procedimentos específicos. Caracterizam-se 
pela passagem de parâmetros e pelas variáveis locais/globais. Facilita a construção de 
programas complexos e a busca por erros. 
 
Programação Orientada a Objeto: consiste em tratar os dados (atributos) e os 
procedimentos (métodos) que atuam sobre os dados como um único objeto. Caracterizada 
pelo Encapsulamento, Herança e Polimorfismo, facilita a construção e manutenção de 
programas muito complexos, implementados por equipes de programadores. 
 
UM PROGRAMA ESCRITO EM C++ OU JAVA PODE NÃO SER UM OOP 
 
 5 
ALGORITMOS 
 
“Processo de cálculo, ou de resolução de um grupo de problemas 
semelhantes, em que se estipulam, com generalidade e sem restrições, as 
regras formais para a obtenção do resultado ou da solução do problema” 
[AURÉLIO] 
 
⇒ Especificar uma seqüência de passos lógicos para que o computador possa executar 
uma tarefa determinada (independe da linguagem) 
 
MANIPULAÇÃO DA INFORMAÇÃO PELOS ALGORITMOS 
 
• Os algoritmos são formados por INSTRUÇÕES que determinam a maneira como os 
DADOS devem ser processados 
• Os dados podem ser numéricos (INTEIROS, REAIS, COMPLEXOS), literais 
(CARACTERES, STRINGS) ou lógicos (BOOLEANOS) 
• As variáveis armazenam os dados e podem ser de qualquer dos tipos acima, e 
ainda multidimensionais (VETORES, MATRIZES) 
 
CARACTERÍSTICAS 
 
• Ter um começo e um fim 
• Não ser ambíguo 
• Receber dados de entrada e gerar informações de saída 
• Todas as etapas do algoritmo devem ser alcançáveis em um tempo finito 
 
FORMAS DE REPRESENTAÇÃO 
 
1) FLUXOGRAMA 
 
Utiliza símbolos gráficos padronizados para representar os algoritmos 
 
 
 
VANTAGENS 
 
• Visualmente muito informativo 
• Padronização mundial 
 
 6 
DESVANTAGENS 
 
• Aumenta de complexidade e pode perder a clareza à medida que o algoritmo 
cresce 
• Difícil de ser traduzido para linguagem de programação 
 
2) LINGUAGEM ALGORÍTMICA 
 
Pseudolinguagem de programação (Portugol, Pseudocódigo, etc), cujos comandos, em 
português ou inglês, descrevem as etapas do algoritmo. Nos algoritmos não estruturados 
as instruções eram numeradas (LABEL) e as repetições eram forçadas por meio de uma 
instrução VÁ PARA (GO TO). 
 
VANTAGENS 
 
• Usa o português ou inglês como base 
• Facilidade na passagem para as linguagens de programação 
• Forma de apresentação condensada 
 
DESVANTAGENS 
 
• Ainda não está padronizado 
• Visualmente pouco informativo 
 
CONCLUSÃO 
As duasformas de apresentação podem ser complementares 
Fluxograma → mais adequado para dar uma visão geral do algoritmo 
 ex.: programa principal que chama várias subrotinas 
Pseudocódigo → mais adequado para especificar cada etapa do algoritmo 
 ex.:detalhar cada subrotina do programa principal 
 
INSTRUÇÕES BÁSICAS DOS ALGORITMOS 
• Declaração de variáveis: var a int[10] ou inteiro a[10] 
• Expressões aritméticas: a+b-c*d/f**g ou a+b-c*d/f^g 
• Expressões lógicas: a.E.b ou (a)E(b) ou a AND b ou a & b 
• Comando de atribuição: a←b-c*d/f**g ou a:=b-c*d/f**g 
• Comando de saída: escreva a ou escreva (a) 
• Comando de entrada: leia a ou leia (a) 
 
 7 
ESTRUTURAS CHAVES PARA A CONSTRUÇÃO DE ALGORITMOS 
 
1) SEQUENCIAÇÃO 
 
Os comandos do algoritmo fazem parte de uma seqüência, onde a ordem na qual ocorrem 
é relevante para o resultado final, pois serão executados um de cada vez, estritamente, de 
acordo com essa ordem 
 
 
b←0 
b←b+1 
a←1/b 
 
 
 
 
 
 
931: b←0 
932: b←b+1 
933: a←1/b 
 
 
2) DECISÃO 
 
Também é conhecida por estrutura condicional, a execução de um ou mais comandos 
depende da veracidade de uma condição. 
 
se a>b então 
 aux←b 
b←a 
a←aux 
senão 
c←a+b 
fim_se 
 
622: se a>b vá para 625 
623: c←a+b 
624: vá para 629 
625: continue 
626: aux←b 
627: b←a 
628: a←aux 
629: continue 
 
 
 
 
 
 
 
 
 
 
 
3) REPETIÇÃO (“looping” ou laço) 
 
Para (FOR): normalmente usado para executar uma seqüência de comandos um número 
pré-definido de vezes, permite definir um contador que pode ser incrementado ou 
decrementado. O contador é uma variável que pode ser utilizada em operações internas ao 
FOR ou pode ser modificada dentro do FOR. No segundo caso é preciso tomar cuidado 
para que não ocorra um looping infinito. 
 
 
 8 
para i=1:2:9 faça 
leia a[i] 
c[i]←a[i]+b 
fim_para 
 
para i=1 até 9 incr 2 faça 
leia a[i] 
c[i]←a[i]+b 
fim_para 
 
para i=1 enquanto i<10 incr 2 
faça 
leia a[i] 
c[i]←a[i]+b 
fim_para 
 
527: i←1 
528: continue 
529: leia a[i] 
530: c[i]←a[i]+b 
531: i←i+2 
532: se i<10 vá para 528 
 
 
 
 
 
 
 
Enquanto (WHILE): executa uma seqüência de comandos caso uma determinada 
condição seja verdadeira, os comandos podem não ser executados nenhuma vez se a 
condição for inicialmente falsa, caso a condição seja verdadeira a seqüência de comandos 
deve eventualmente torná-la falsa para evitar o looping infinito. 
 
cont←0 
enquanto a≥b faça 
a←a-b 
cont←cont+1 
fim_enquanto 
 
874: cont←0 
875: continue 
876: se a<b vá para 880 
877: a←a-b 
878: cont←cont+1 
879: vá para 875 
880: continue 
 
 
 
 
Repita (REPEAT-UNTIL/DO-WHILE): executa uma seqüência de comandos até que uma 
determinada condição se torne verdadeira (ou enquanto permaneça verdadeira, no caso 
do DO-WHILE), os comandos são executados pelo menos uma vez, caso a condição seja 
falsa a seqüência de comandos deve eventualmente torná-la verdadeira para evitar o 
looping infinito. 
 9 
 
 
i←0 
repita 
i←i+1 
leia a[i] 
c[i]←a[i]+b 
até a[i]<0 
fim_repita 
 
 
i←0 
faça 
i←i+1 
leia a[i] 
c[i]←a[i]+b 
enquanto a[i]≥0 
fim_faça_enquanto 
 
 
1054: i←0 
1055: continue 
1056: i←i+1 
1057: leia a[i] 
1058: c[i]←a[i]+b 
1059: se a[i]≥0 vá para 1055 
 
 
 
 
 
 
 
REFINAMENTOS SUCESSIVOS 
 
Um algoritmo estará pronto quando todas as suas instruções forem passíveis de serem 
traduzidas para a linguagem de programação e sua execução alcançar o resultado 
pretendido. 
 
Caso contrário, as instruções devem ser desdobradas em novas instruções, que 
constituirão um refinamento do algoritmo inicial. Isso é feito sucessivamente para todos os 
comandos, até que o algoritmo esteja pronto. 
 
O algoritmo para um problema único pode não ser único ⇒ programadores diferentes 
geram algoritmos diferentes, uns mais eficientes e outros menos, embora todos efetivos ⇒ 
mesmo os algoritmos prontos são passíveis de melhorias. 
 
⇒⇒⇒⇒ A partir de um primeiro esboço (estrutura base do algoritmo) faz-se sucessivos 
refinamentos. 
⇒⇒⇒⇒ Primeiro se constrói um algoritmo efetivo depois se busca o “ótimo”. 
⇒⇒⇒⇒ Partes do algoritmo que aparecem mais de uma vez podem ser agrupadas como 
uma única sub-rotina que será chamada repetidas vezes. 
⇒⇒⇒⇒ É fundamental documentar o algoritmo com nome, autor, data e objetivo do 
algoritmo, descrição das variáveis e comandos, seqüência de comandos ou sub-
rotinas. 
 
 10
LINGUAGEM C 
 
Desenvolvida por Dennis Ritchie, baseada na linguagem B de Ken Thompson que se 
originou da linguagem BCPL de Martin Richards. É considerada uma linguagem de médio 
nível por permitir a manipulação de bits, bytes e endereços de memória. 
 
É uma linguagem estruturada e permite a criação de funções, embora não permita a 
criação de funções dentro de funções. Essa capacidade de construção de sub-rotinas 
isoladas torna a linguagem C muito conveniente para a implementação de programas 
complexos. 
 
Outra característica interessante da linguagem C são os blocos de códigos, ie, grupos de 
comando colocados dentro de chaves, que permitem uma implementação mais eficiente e 
clara dos algoritmos. 
 
A linguagem C tem apenas 32 palavras-chave reservadas: 
 auto break case char const continue 
 default do double else enum extern 
 float for goto if int long 
 register return short signed sizeof static 
 struct switch typedef union unsigned void 
 volatile while 
 
A linguagem C é case sensitive. Por ser muito enxuta, a linguagem C não possui palavras-
chave para várias funções que são intrínsecas em outras linguagens, (operações de 
entrada/saída, etc). Por isso, os programas em linguagem C normalmente incluêm 
chamadas a várias funções contidas na biblioteca C padrão, cujo código-objeto é 
adicionado, durante a linkedição, ao código do programa para formar o programa 
executável. 
 
 11
A estrutura geral de um programa em C é: 
 #include <stdio.h> //inclusões de bibliotecas 
float x; //declaração de variáveis globais 
 int main() //função principal 
 { //início da função 
 int x; //declaração de variáveis locais 
 printf(“%i”,x); //comandos 
 } //fim da função principal 
 float f(float y) //tipo devolvido, função e argumentos 
 { //início da função 
 return x+y; //comandos 
 } //fim da função 
 
A linguagem C apresenta cinco tipos básicos de dados (char, int, float, double e void) que 
podem ser modificados (signed, unsigned, long e short): 
char (8 bits): 256 caracteres (letras, números, símbolos) 
int (16 bits): números inteiros (-32.767 a 32.767) 
unsigned int (16 bits): inteiros (0 a 65.535) 
long int (32 bits): inteiros (-2.147.483.647 a 2.147.483.647) 
unsigned long int (32 bits): inteiros (0 a 4.294.967.295) 
float (32 bits): números reais (16 dígitos e expoentes ±38) 
double (64 bits): reais (16 dígitos e expoentes ±308) 
 
Os nomes de identificadores (variáveis, funções, rótulos, etc) devem começar com uma 
letra ou um sublinhado, seguidos de letras, números ou sublinhados. É conveniente que os 
nomes sejam significativos, mas não excessivamente longos: 
auxiliar vetor1 produto_34 
 
Todas as variáveis devem ser declaradas antes de serem usadas. A declaração pode ser 
feita fora de todas as funções (variáveis globais), dentro dos blocos (variáveis locais) e na 
definição dos parâmetros das funções (parâmetros formais). As variáveis podem ser 
unidimensionais ou multidimensionais (vetores, matrizes, etc). 
 12
 int i, j; 
 float a[10][10], x[10], c;int main() 
 { 
 int x; 
 char c; 
 { 
 int c; 
 
⋮
 
 
As variáveis locais são alocadas ao iniciar a execução do bloco e são destruídas ao 
término desta. Os parâmetros formais das funções se comportam como variáveis locais. 
Quando houver variáveis locais e globais com mesmo nome, o bloco em questão irá 
processar apenas a variável local. 
 
Na linguagem C o comando de atribuição é feito utilizando o sinal =, podendo ser feita 
atribuição múltipla (x=y=10;), ou dentro de qualquer expressão (havendo sempre a 
conversão para o tipo da variável). 
 
As variáveis podem ser modificadas por const (impede sua alteração ao longo do 
programa=>inicialização explícita ou alteração via hardware) e volatile (informa ao 
compilador que a variável pode ser alterada independentemente do programa) 
 const int a=10; 
 
A linguagem C permite que um programa seja compilado a partir de arquivos separados, 
para facilitar o gerenciamento das variáveis pode-se utilizar o comando extern que indica 
em cada arquivo as variáveis globais: 
 Arquivo 1 Arquivo 2 
 int x, y; extern int x,y; 
 int main() void funcao1(void) 
 { { 
 
⋮
 
⋮
 
 } } 
 
As variáveis locais podem manter seu valor entre chamadas da função com o uso de static: 
 static int n; 
 13
 
Esse mesmo modificador aplicado a uma variável global faz com que a mesma seja 
reconhecida apenas no arquivo em que foi declarada. Se for usado o modificador register o 
compilador irá fazer com que a variável em questão seja armazenada no dispositivo de 
acesso mais rápido disponível. Portanto, ela poderá não ter endereço, caso seja 
armazenada em registradores. 
 
As variáveis podem ser inicializadas na declaração fazendo a atribuição de alguma 
constante (do tipo int, char, float, etc.). Variáveis locais e register não inicializadas 
possuem valores desconhecidos, variáveis globais e locais static não inicializadas 
possuem valor zero. Constantes iniciadas em 0 são octais e em 0x são hexadecimais. 
Constantes caractere devem ser escritas entre aspas simples ‘a’, e string entre aspas 
duplas “abc”. 
 int i=1, hex=0x80, oct=012; 
 float a=3.4F, b=-4.35e-3; 
 
Caracteres não imprimíveis são especificados por meio de barras invertidas: 
\b retrocesso \0 nulo \” \’ aspas 
\\ barra invertida \n nova linha \v tabulação vertical 
\r retorno \a beep \t tabulação horizontal 
 
 14
OPERADORES 
 
A linguagem C possui diversos tipos de operadores: 
Aritméticos: - + * / % -- ++ 
Obs: 1) na divisão inteira ou caractere o resto é truncado. 
 2) o sinal -- ou ++ pode ser colocado antes ou depois da variável. 
 3) x++ é mais eficiente do que x=x+1. 
Lógicos: && || ! 
Obs: 1) na linguagem C falso é zero e verdadeiro é qualquer não zero. 
Relacionais: > >= < <= == != 
Bit a bit: & | ^(xor) ~(comp. de 1) >> <<(deslocamentos) 
Ternário: y=x>9?100:200; (se x>9 então y recebe 100 cc. recebe 200) 
Ponteiro: &(endereço do ponteiro) *(conteúdo do ponteiro) 
Obs: 1) um ponteiro é o endereço na memória de uma variável. 
 2) variáveis ponteiro devem ser declaradas: char eu, *tu, eles; 
 3) Nesse caso, no endereço apontado por tu tem um caractere. 
Tamanho em bytes: sizeof x; sizeof (int); 
Vírgula: x=(y=3,y+1); � y=3; x=y+1; 
Ponto: cadastro.peso=74.5; (indica um elemento de uma estrutura) 
Seta: p->peso=74.5 (mesmo efeito do ponto se p é um ponteiro para peso) 
Casts: (float) 5/2; (força um determinado tipo em uma expressão) 
C reduzido: -= += *= /= (x=x+10 � x+=10) 
Obs: 1) ordem de precedência: 
+ → - 
() 
[] 
-> 
! ~ 
++ -- 
- 
(tipo) 
* & 
sizeof 
* 
/ 
% 
+ 
- 
<< 
>> 
< 
<= 
> 
>= 
== 
!= & ^ | && || ?: 
= 
+= 
-= 
*= 
/= 
%= 
, 
2) Os parênteses podem ser usados para alterar a ordem de precedência. 
 3) Durante a avaliação de uma expressão é feita a promoção de tipo. 
 
 15
I/O PELO CONSOLE 
 
A linguagem C não define nenhuma palavra-chave para operações de entrada/saída, que 
são efetuadas por funções de biblioteca (stdio.h). As funções a seguir realizam as 
operações de entrada/saída via console (teclado, monitor). 
 
Entrada/saída não formatada: 
letra=getchar(); Lê o caractere (mostra na tela, não é iterativa). 
putchar(letra); Mostra a letra na tela (considera stdin e stdout). 
letra=getc(fp); Lê o caractere (mostra na tela, não é iterativa). 
putc(letra,fp); Mostra a letra na tela (considera a stream fp). 
gets(frase); Lê a linha até o return; acrescenta nulo no fim. 
puts(frase); Mostra a frase (considera stdin e stdout). 
cin>>variavel; Leitura do C++ para qualquer tipo de variável. 
cout<<variavel; Saída do C++ para qualquer tipo de variável. 
 
Entrada/saída formatada: 
printf(“caractere %c.\n”,letra); 
printf(“numero %f real.\n”,x); 
printf(“numero %5d com cinco digitos.\n ”,i); 
printf(“completa %05d com zeros.\n ”,i); 
printf(“frase %5.7s de 5 a 7 caracteres.\n ”,tu); 
printf(“numero %.3f com 3 casas decimais.\n ”,x); 
printf(“%5.3f com 5 dig. e 3 casas dec..\n ”,x); 
printf(“%-5.3f justificado a esquerda.\n ”,x); 
scanf(“%d”, &i); Lê um decimal e armazena em i. 
scanf(“%c”, &a); Lê um caractere e armazena em a. 
scanf(“%s”, palavra); Lê uma string até o 1o espaço em branco. 
Obs: 1) a leitura com scanf() não precisa ser necessariamente formatada. 
 2) espaços em branco ou caracteres em scanf() fazem a leitura ignorar a 
 mesma quantidade de espaços ou os mesmos caracteres. 
 3) comentários podem ser colocado entre /* e */ ou após //. 
 4) a chamada para a biblioteca é feita por: #include <stdio.h> 
 16
7) a entrada não iterativa requer a digitação do enter após o dado a ser lido, esse 
enter permanece na stream de entrada e pode ser lido posteriormente 
 
Especificadores de formato: 
%c %s caractere e string %d %i inteiro decimal 
%u inteiro decimal sem sinal %p ponteiro 
%e %E notação científica com e ou E %f notação em ponto flutuante decimal 
%g %G usa o formato mais curto entre, %e ou %f e %E ou %f 
%#e %#E %#f %#g %#G força a colocação do ponto decimal 
%o octal %#o força a colocação de 0 
%x hexadecimal sem sinal (abcdef) %#x força a colocação de 0x 
%X hexadecimal sem sinal (ABCDEF) %#X força a colocação de 0x 
printf(“pont aponta %n um inteiro com valor 12”, &pont); 
printf(“%% escreve o simbolo de porcentagem”); 
printf(“%*.*f deixa a precisão como argumento”,4,2,x); 
scanf(“%d%*c%d”,&x,&y); lê o caractere mas não o armazena 
scanf(“%[abc]s”,s1,s2); digitando abcdabc s1=”abc” e s2=”dabc” 
 idem p/ [a-b], mas o inverso p/ [^abc] 
 
 17
FUNÇÕES MATEMÁTICAS 
 
Todas a funções a seguir estão definidas na biblioteca math.h. Todos os ângulos são 
considerados como radianos, os argumentos das funções devem ser escalares ou 
elementos de vetor e matriz, mas nunca o vetor e a matriz. 
cos(x) sin(x) tan(x) cosseno, seno e tangente de x 
acos(x) asin(x) atan(x) arco cosseno, arco seno e arco tangente de x 
atan2(x,y) arco tangente de x/y 
cosh(x) sinh(x) tanh(x) cosseno, seno e tangente hiperbólicos de x 
ceil(x) floor(x) arredondamento inteiro de x, para cima e para baixo 
exp(x) log(x) log10(x) exponencial, logaritmo natural e na base 10 de x 
fabs(x) fmod(x,y) valor absoluto de x e resto da divisão inteira de x por y 
ldexp(x,y) retorna x*2^y 
frexp(x,y) retorna a mantissa de x (0,5 a 1) e armazena a potência de 2 em y 
modf(x,y) retorna a parte inteira de x e armazena a parte decimal de x em y 
pow(x,y) sqrt(x) x elevado a y e raiz quadrada de x 
 
 18
ESTRUTURAS DE CONTROLE DE FLUXO DO PROGRAMA 
 
O fato da linguagem C considerar como resultado falso de um teste condicionalo valor 0 e 
como valor verdadeiro qualquer valor diferente de 0 permite a construção de códigos 
extremamente eficientes. 
 
Estruturas de seleção: 
 
 if (a>b) printf(“\n%i”,a); 
 else printf(“\n%i”,b); 
 
Se a expressão entre parênteses resulta em um valor diferente de zero (verdadeiro), o 1o 
comando é executado, caso contrário o 2o comando é executado. 
Obs: 1) a expressão não precisa ser necessariamente um teste lógico. 
2) o 1o comando pode ser um comando único, um bloco ou estar ausente. 
3) o else é opcional e se refere sempre ao if anterior do mesmo bloco. 
4) o 2o comando pode ser outro if formando uma escada if-else-if. 
5) o operador ternário ? pode substituir o if em algumas situações. 
 
 switch (a+b) 
{ 
case 1: 
printf(“a+b=1”); 
break; 
case 2: 
printf(“a+b=2”); 
break; 
default: 
 printf(“a+b=%i”,a+b); 
} 
 
Se o valor da expressão entre parênteses for igual à constante de algum case, o comando 
subseqüente será executado, caso contrário o comando subseqüente ao default será 
executado. O padrão ANSI C estabelece um mínimo de 257 cases. As mesmas 
observações do if são válidas para o switch. Sendo que default e break são opcionais. 
 19
Estruturas de repetição: 
 
 for (int i=0;i<=100;i=i+1) printf(“\n%i”,i); 
 
A inicialização (1o campo) geralmente atribui um valor inicial à variável de controle do laço, 
contador i, que é alterada conforme o comando de incremento (3o campo). Nesse caso, o 
comando subseqüente ao for é repetido para cada valor do contador enquanto o comando 
de condição (2o campo) estiver satisfeito, ie, resulte em um valor não zero. 
 
Obs: 1) a condição é verificada antes do comandof, e o incremento depois. 
 2) inicialização/condição/incremento podem ser qualquer expressão de C. 
3) o comandof também pode alterar o contador (cuidado com laço infinito). 
4) pode-se ter mais de um contador, nesse caso a inicialização e o incremento são 
separados por vírgulas. 
 
 while (i<=100) printf(“\n%i”,i++); 
 
O comando subseqüente ao while é executado repetidamente enquanto a condição entre 
parênteses tiver valor não-nulo, verdadeiro. A condição é avaliada no início do laço e pode 
ser qualquer expressão de C. Comando pode estar ausente ou ser um bloco de comando. 
A variável de controle, contador i, deve ser declarada e inicializada previamente. 
 
 do printf(“\n%i”,i++); while (i<=100); 
 
O comando subseqüente ao do é executado repetidamente enquanto condição entre 
parênteses tiver valor não-nulo, verdadeiro. A condição é avaliada no fim do laço. O 
comando pode ser único ou ser um bloco de comandos. Convém sempre usar um bloco de 
comandos com tabulação, mesmo quando o comando for único, para aumentar a clareza 
do código. 
 
Comandos de desvio incondicional: 
 
 return x; 
 
Retorna de uma função, ie, volta ao ponto onde foi feita a chamada da função. Se tiver um 
valor ou variável associada, esse será o valor da função. É similar à última } da função. 
 
 20
 goto ponto1; 
 
⋮
 
ponto1: 
 
O comando goto desvia o fluxo de execução do programa para o rótulo correspondente, 
ponto1. O desvio pode ser feito para frente ou para trás. Rótulo é um identificador que 
segue as regras para os nomes das variáveis. É muito pouco utilizado por ser um resquício 
da programação não estruturada. 
 
 break; 
 
Termina um case em um comando switch ou força a fim de um laço no qual esteja inserido, 
retornando para o comando seguinte ao laço. Nesse último caso, normalmente vem 
associado a uma estrutura de seleção if. 
 
 exit(); 
 
Força o fim de um programa retornando ao sistema operacional. 
 
 continue; 
 
Força a ocorrência da próxima iteração do laço no qual está inserida, pulando os códigos 
restantes do comando. Para o laço for, força a verificação da condição e a execução do 
incremento, para os laços while e do-while, força a verificação da condição. 
 21
VETORES E MATRIZES 
 
Uma matriz é uma coleção de variáveis do mesmo tipo que é referenciada por um nome 
comum. Cada elemento da coleção é acessado por um índice. Em linguagem C os 
elementos de uma matriz ocupam posições adjacentes na memória e os índices se iniciam 
com 0, e não com 1. 
 
 float x[10][5]...[12] 
 
A quantidade de memória utilizada para armazenar a matriz é: 
 
sizeof(tipo)*10*5*...*12 
 
Em linguagem C cabe ao programador se certificar que os limites da matriz não serão 
excedidos ao longo do programa. O nome da matriz sem índices especifica o endereço do 
primeiro elemento que pode ser usado como ponteiro para a matriz: 
 
 int *p; 
 int sample[10]; 
 p=sample; //é idêntico a 
 p=&sample[0]; 
 sample[5]=10; //é idêntico a 
 *(p+5)=10; 
 
O ponteiro para a matriz é muito útil para passar a matriz como argumento de uma função, 
já que a matriz propriamente dita não pode ser passada. Vetores são matrizes 
unidimensionais, sendo que, em linguagem C, as strings são vetores de caracteres que 
terminam em nulo “\0”. O uso de matrizes de caracteres não é raro, sendo que cada linha 
da matriz pode ser tratada como uma string. 
 
char palavra[15]; 
 char texto[20][80]; 
 gets(texto[2]); 
 
A inicialização das matrizes pode ser feita durante a declaração (inclusive sem 
dimensioná-las): 
 
 int i[2][2]={1,34,43,25}; 
 int i[][2]={1,34,43,25}; 
 char palavra[6]=”UNESP”; 
 char palavra[6]={‘U’,’N’,’E’,’S’,’P’,’\0’}; 
 char palavra[]=”UNESP”; 
 
Os comandos cin e scanf buscam todos os caracteres até a ocorrência de um espaço em 
branco. O comando gets busca todos os caracteres até a ocorrência do enter. As 
constantes caractere de barra invertida permitem inserir caracteres não imprimíveis, p.ex. 
‘\n’ indica o começo de uma nova linha. Convém lembrar que os elementos de uma matriz 
ocupam posições adjacentes na memória, mas duas variáveis declaradas em seqüência 
não. 
 22
FUNÇÕES DE CADEIA DE CARACTERES: <string.h> 
 
strcpy(s1,s2) copia s2 para s1 e retorna s1; 
strncpy(s1,s2,n) copia no máximo n caracteres da cadeia s2 para s1, 
 retorna s1 e preenche as posições restantes com ‘\0’; 
strcat(s1,s2) concatena s2 com s1, retorna s1 e finaliza com ‘\0’, 
 s1 dever ter tamanho suficiente para “receber” s2; 
strncat(s1,s2) concatena no máximo n caracteres de s2 com s1, retorna 
 s1 e finaliza com ‘\0’, 
strcmp(s1,s2) compara s1 com s2, retorna negativo se s1<s2, zero se 
 s1=s2 e positivo se s1>s2; 
strncmp(s1,s2,n) compara no máximo n caracteres de s1 com s2, retorna 
 negativo se s1<s2, zero se s1=s2 e positivo se s1>s2; 
strchr(s1,s2) retorna um ponteiro à primeira ocorrência de s2 em s1, ou
 NULL caso não ocorra; 
strrchr(s1,s2) retorna um ponteiro à última ocorrência de s2 em s1, ou
 NULL caso não ocorra; 
strspn(s1,s2) retorna o comprimento da substring inicial de s1 
 consistindo de caracteres em s2; 
strcspn(s1,s2) retorna o comprimento da substring inicial de s1 
 consistindo de caracteres que não estão em s2; 
strspbrk(s1,s2) retorna apontador para a primeria ocorrência em s1 de
 qualquer caractere de s2, ou NULL se não houver; 
strstr(s1,s2) retorna apontador para a primeira ocorrência de s2 em s1, ou 
NULL se não houver; 
strlen(s1) retorna o comprimento de s1; 
strspn(s1,s2) retorna o comprimento da substring inicial de s1 
 consistindo de caracteres em s2; 
strcoll(s1,s2) compara s1 com s2 segundo a localidade especificada por
 setlocale(), retorna negativo se s1<s2, zero se s1=s2 e 
 positivo se s1>s2; 
 
 23
PONTEIROS 
 
Um ponteiro é uma variável que contém um endereço de memória. Se esse endereço é o 
de uma outra variável, a primeira variável aponta para a segunda. 
 
 char *p; 
 
Na declaração de um ponteiro, o tipo especificado é o da variável apontada. Assim, a 
variável p armazena um inteiro queé o endereço de uma variável caractere. O operador 
unário & devolve o endereço de seu operando. Enquanto o operador unário * devolve o 
valor armazenado no endereço de seu operando: 
 
 p=&palavra; 
 palavra=*p; 
 
Uma variável ponteiro pode receber o valor de outro ponteiro, ser incrementada, 
decrementada ou deslocada: 
 
 p1=p2; 
 p1++; 
 p2--; 
 p1=p1+12; 
 
Obs: os incrementos, decrementos e deslocamentos são feitos segundo o tipo da variável 
apontada. Assim, se o tipo ocupa mais de uma posição de memória um incremento pode 
não levar para a posição subseqüente da memória. 
 
Um ponteiro pode apontar para outro ponteiro (indireção múltipla): 
 
float **p1, *p2, x; 
p2=&x; 
p1=&p2; 
 
Durante a compilação de um programa são criadas quatro áreas de memória: código do 
programa, variáveis globais, pilha e heapy. Variáveis globais são alocadas durante a 
compilação e variáveis locais usam a pilha, mas nenhuma delas pode ser acrescentada 
durante a execução. A menos que se use alocação dinâmica da memória heapy. Da 
biblioteca <stdlib.h> podemos utilizar a função malloc() para alocar memória 
dinamicamente e free() para liberá-la: 
 
 char *p; 
 p=(char*)malloc(1000); //aloca 1000 bytes 
 p=(char*)malloc(500*sizeof(int)); //melhor portabilidade 
 
Como a memória é finita convém sempre verificar se o ponteiro não é nulo: 
 
 if (!(p=(char*)malloc(20*sizeof(float)))) { 
 printf(“SEM MEMÓRIA.”); 
 exit(1); 
 } 
As operações utilizando ponteiros para as variáveis são, em geral, mais rápidas que as 
operações utilizando as próprias variáveis. Além disso, a alocação dinâmica de memória, 
 24
permite a implementação de programas bastante eficientes, inclusive utilizando vetores e 
matrizes de dimensão genérica: 
 
 #include stdlib.h> 
 float *vetor,**matriz; 
 
 int main(void) 
 { 
 int i,n=10; 
 vetor=(float*)malloc(n*sizeof(float)); 
 matriz=(float**)malloc(n*sizeof(float)); 
 for (i=0;i<n;i++) 
 matriz[i]=(float*)malloc(n*sizeof(float)); 
 } 
 
Erros cometidos com ponteiros são, em geral, difíceis de serem descobertos. Podendo ser 
bastante graves quando se armazena um dado em uma posição errada da memória 
(substituindo outras variáveis ou mesmo partes do código). Os erros mais comuns são: 
 
 int *p, x=10; 
 *p=x; //ponteiro (endereço) não inicializado 
 p=x; //erro de sintaxe, o correto seria p=&x; 
 25
FUNÇÕES 
 
Funções são estruturas que facilitam a implementação e verificação dos programas por 
dividi-los em blocos independentes (C não permite funções dentro de funções, assim não é 
“estruturada em blocos”). Em C tem a seguinte forma geral: 
 
tipo nome(parâmetros) 
{ 
comandos; 
} 
 
O tipo default de retorno é int. Os parâmetros são os argumentos da função, eles se 
comportam como variáveis locais e sua declaração tem a seguinte forma geral: 
 
tipo nome1, tipo nome2, ... , tipo nomeN 
 
A linguagem C permite especificar uma função com quantidade de parâmetros variável, 
desde que seja maior ou igual a 1: 
 
 int func(int a, int b, ...) 
 
Os comandos no corpo da função determinam a atividade exercida por ela e não são 
acessíveis aos demais comandos do programa, pois tem escopos diferentes. A chamada 
da função é feita simplesmente pelo seu nome: 
 
t=4.0; 
x=sqrt(t); 
 
Nesse caso, os parâmetros formais da função copiam os valores dos parâmetros que são 
passados para a função. Assim, os valores que os parâmetros têm fora da função não são 
alterados, mesmo que os parâmetros formais sejam alterados no corpo da função 
(“chamada por valor”). 
 
Se as alterações nos parâmetros formais, dentro da função, alteram os valores dos 
argumentos que foram passados temos a "chamada por referência". A linguagem C só faz 
chamadas por valor. Quando se deseja alterar as variáveis que são passadas para uma 
função, seus parâmetros formais devem ser declarados como sendo ponteiros. Nesse 
caso, na chamada da função os argumentos devem ser precedidos por um &. 
 26
A passagem de matrizes como argumento de funções é uma exceção, pois é feita sempre 
por referência. Podendo ser declarada de maneiras diferentes, evitando sempre a 
ambigüidade em matrizes multidimensionais: 
 
Protótipo argumentos chamada da função 
void f(int vet[50]); int x[50] f(x); 
void f(int vet[]); int x[50] f(x); 
void f(int *vet); int x[50] f(x); 
void g(float mat[50][10]); float A[50][10] g(A); 
void g(float mat[][10]); float A[50][10] g(A); 
 
A função main() pode ter parâmetros formais (argumentos de linha de comando) que 
seguem o nome do programa na linha de comando do sistema operacional: 
 
int main (int argc,char *argv[]); 
 
O argc (argument count) é um inteiro e possui o número de argumentos com os quais a 
função main() foi chamada na linha de comando (vale no mínimo 1). O argv (argument 
values) é um ponteiro para uma matriz de strings. Cada string desta matriz é um dos 
parâmetros da linha de comando (argv[0] sempre aponta para o nome do programa), 
portanto deve-se fazer as conversões adequadas: 
 
i=atoi(argv[1]); converte o segundo argumento em inteiro 
x=atof(argv[2]); converte o segundo argumento em real 
 
O comando return provoca o encerramento imediato da função e, se o valor de retorno é 
informado, a função retorna este valor, que tem que ser compatível com o tipo declarado 
para a função: 
 
 int mul(int a, int b) 
 { 
 return a*b; 
 } 
 
Como o default para tipos de funções é o int e o C pode não fazer a verificação de tipo, o 
uso incorreto das funções podem gerar resultados bizarros. Para evitar esse tipo de erro foi 
 27
criado o protótipo de função, que consiste em declarar no início do programa todas a 
funções (com seus tipos e parâmetros) que serão escritas: 
 
tipo func(tipo var1, tipo var2, ..., tipoN varN); 
 
Obs: 1) uma alternativa para os protótipos seria escrever as funções antes da função 
main(), de modo que o compilador já saiba durante a compilação da chamada das 
funções quais são os parâmetros e os tipos retornados (pode não funcionar quando 
se tem o programa espalhado por vários arquivos). 
 2) uma função que retorna um ponteiro deve ser declarada como sendo um ponteiro 
para o tipo de variável apontada pelo ponteiro de retorno. 
 3) uma função que não retorna valor pode ser declarada com void para evitar a 
atribuição incorreta do valor retornado. 
 
Em C, uma função pode chamar a si própria, se tornando recursiva (p/ex. cálculo do 
fatorial). A maioria das funções recursivas não torna o programa mais eficiente (em termos 
de linhas de códigos, uso de memória ou tempo de execução), mas alguns algoritmos são 
mais facilmente implementados recursivamente. 
 
Obs: é essencial que funções recursivas tenham critérios de parada para que não 
entrem em loop infinito. 
 
 28
ARQUIVOS 
 
A linguagem C permite que o programa manipule um arquivo armazenado em um 
dispositivo de memória secundária utilizando funções de biblioteca. C++ suporta todo o 
sistema de arquivo do C, a recíproca não é verdadeira. Lembrando que a linguagem C++ é 
orientada, e implementar um programa orientado a objeto é mais do que simplesmente 
utilizar comandos do C++. 
 
Para a linguagem C qualquer dispositivo de E/S é um arquivo: HD, disquete, impressora, 
teclado, vídeo, etc . O sistema de E/S da linguagem C fornece um nível de abstração entre 
o programador e o dispositivo utilizado. Essa abstração é chamada de stream e o 
dispositivo real é chamado de arquivo. Existem dois tipos de streams: texto (seqüência de 
caracteres) e binária (seqüência de bytes). 
 
Uma stream é associada a um arquivo específico realizando um processo de abertura, 
com recursos diferentes para cada arquivo, p.ex. o acesso aleatório existe quando o 
arquivo é um disco mas não parao teclado. No fechamento ocorre a dissociação da 
stream e o conteúdo desta é descarregado no arquivo, flushing. Todos os arquivos são 
fechados automaticamente ao fim do programa main ou com uma chamada a exit(). O 
fechamento não se dá quando ocorre uma quebra do programa ou quando se chama 
abort(). 
 
A biblioteca com as funções para manipulação de arquivos é <stdio.h>. Um ponteiro de 
arquivo é um ponteiro para informações que definem o arquivo: nome, status, posição atual 
do arquivo. As operações das funções de E/S são feitas a partir desse ponteiro. A 
declaração é feita como: 
 
FILE *arq; 
 
As funções mais comuns da biblioteca são: 
 
arq=fopen(“dados.dat”,”modo”); abre um arquivo, devolve o ponteiro 
fclose(arq); fecha um arquivo 
 
Obs: 1) dados.dat: nome do arquivo (ou path) 
2) modo: caractere que indica o modo de abertura do arquivo 
r: abre arquivo de texto, somente leitura 
w: cria arquivo de texto, somente escrita 
a: anexa novos dados, arquivo de texto 
 29
 3) b indica que o arquivo é binário: rb, wb e ab 
4) + indica que o arquivo é de leitura e escrita: r+, w+, a+, rb+, wb+ e ab+ 
 5) w e wb criam um arquivo novo ou sobrepõe o antigo com um vazio 
 ⇒ ao manipular um arquivo existente deve-se usar leitura ou leitura e escrita 
 6) é sempre conveniente testar a abertura do arquivo 
 
fputc(ch,arq); escreve um caractere num arquivo 
ch=fgetc(arq); lê um caractere do arquivo 
fputs(s1,arq); escreve uma string num arquivo 
fgets(s1,n,arq); lê uma string de até n-1 caracteres do arquivo 
 
Obs: 1) char: variável do tipo caractere que será lida/escrita no arquivo 
2) s1: variável string que será escrita no arquivo 
 
fwrite(&var,nbytes,cont,arq); escreve qualquer tipo de dado 
fread(&var,nbytes,cont,arq); lê qualquer tipo de dado 
 
Obs: 1) var: variável cujo conteúdo será escrito ou lido no arquivo 
2) nbytes: número de bytes do conteúdo 
3) cont: quantos itens, cada um de nbytes, serão escritos ou lidos 
4) para cada tipo de variável (int, float, double, etc.) nbytes pode ser determinado 
com o comando: sizeof(tipo) 
 
fprintf(arq,“texto+spf”,&var1,...); escreve qualquer tipo de dado 
fscanf(arq,“texto+spf”,&var1,...); lê qualquer tipo de dado 
 
Obs: 1) spf: especificadores de formato, caractere iniciado com % 
2) var1,...: variáveis cujos conteúdo serão escritos ou lidos 
 
Embora esta seja a forma mais prática de manipular arquivos devido ao fato de os dados 
estarem em ASCII, o tempo de conversão do binário para ASCII faz com que essa não 
seja a forma mais rápida 
 
rewind(arq); reposiciona o indicador no início do arquivo 
 30
fseek(arq,nbytes,pos); posiciona o indicador num endereço específico 
 
Obs: 1) nbytes: quantidade de bytes deslocados a partir da posição pos 
2) pos: macro que define o ponto de origem para o posicionamento 
SEEK_SET: posição inicial 
SEEK_CUR: posição atual 
SEEK_END: posição final 
 
feof(arq); verifica se o final do arquivo foi atingido 
 
Obs: 1) Valor retornado zero ⇒ fim do arquivo não atingido 
2) Valor retornado não zero ⇒ fim do arquivo atingido 
 
remove(arq); apaga um arquivo 
 
 31
TIPOS DE DADOS DEFINIDOS PELO USUÁRIO 
 
A ESTRUTURA é uma coleção de variáveis de tipos diferentes, referenciadas por um 
nome, conveniente para agrupar informações relacionadas. A forma geral é:
 
 struct ident { 
tipo campo1; 
... 
tipo campoN; 
} var1,..., varM; 
 
struct ident { 
tipo campo1; 
... 
tipo campoN;}; 
struct ident var1,..., varM; 
 
Um exemplo seria a identificação dos assinantes numa lista telefônica: 
 
struct assinante { 
char nome[30]; 
char rua[20]; 
long int cep; 
char tel[9]; 
} residencial[1000], comercial[200]; 
 
Os campos da estrutura são acessados usando o operador ponto: 
 
 residencial[10].cep=17030; 
 printf(“%d”,comercial[0].cep); 
 scanf(“%d”,&comercial[0].cep); 
 scanf(“%s”,comercial[0].tel); 
 scanf(“%c”,&comercial[0].tel[2]); 
 
 gets(residencial[98].rua); 
 
O campo de uma estrutura1 pode ser uma estrutura2, para acessar um campoX desta 
última a forma geral é: 
 
 estrutura1.estrutura2.campoX 
 
O padrão C ANSI permite a atribuição de estruturas, eliminando a necessidade de 
atribuição campo a campo: 
 
 residencial[23]=comercial[11]; 
 
Uma estrutura inteira pode ser passada para uma função. A passagem da estrutura é feita 
por valor: a estrutura, que está sendo passada, é copiada, campo por campo, em uma 
variável local da função, não alterando a variável fora da função. Assim, os parâmetros da 
função devem ser declarados como estruturas (as mesmas dos argumentos), e estas 
devem ser declaradas como estruturas globais (fora do main). Na linguagem C pode-se 
declarar um ponteiro para uma estrutura: 
 
struct assinante *p; 
 
Isso permite a passagem por referência de estruturas como argumentos de funções, o que 
torna o programa mais rápido. Nesse caso, o acesso aos campos da estrutura é feita por 
meio do operador seta (->): 
 
 p=&assinante[77]; 
 p->cep=37140; 
 
Para economizar memória, se adequar a dispositivos de hardware ou para atender rotinas 
de criptografia pode ser necessário acessar individualmente os bits dentro dos bytes. Isso 
pode ser feito utilizando os campos de bits. No exemplo abaixo, status guarda informações 
booleanas distintas em cada um de seus bits, embora se possa usar mais de um bit para o 
mesmo campo: 
 
 
struct status_type { 
unsigned delta_cts: 1; 
unsigned delta_dsr: 1; 
... 
unsigned dsr: 1; 
unsigned ring: 1; 
unsigned rec_line: 1; 
} status; 
 
Uma declaração union determina uma única localização de memória onde podem estar 
armazenadas várias variáveis diferentes em momentos diferentes. Portanto, o compilador 
reserva espaço suficiente para acomodar o maior tipo dentre os campos (isso permite 
tornar o código independente da máquina). A declaração e acesso de uma união são 
semelhantes as de uma estrutura: 
 
union identificador { 
tipo nome1; 
... 
tipo nomeN; 
} var1, ... , varM; 
 
Uma enumeração é um conjunto de variáveis inteiras que especifica todos os valores 
legais que uma variável desse tipo pode ter. A forma geral é: 
 
 enum identificador {lista_de_valores} variáveis; 
 
Cada valor da lista corresponde a um inteiro começando em 0, que pode ser inicializado, 
no exemplo abaixo mao=0, balaio=10 e carro=11: 
 
 enum medida {mao, balaio=10, carro} volume; 
 
O operador sizeof (não é função, pois a substituição é feita na compilação) retorna o 
tamanho em bytes de variáveis ou de tipos, e pode ser usado para garantir portabilidade 
ou fazer alocação dinâmica de memória de tipos definidos pelo usuário. O sizeof admite 
duas formas: 
 
 
sizeof variável sizeof (tipo) 
O comando typedef permite ao programador definir um novo nome para um determinado 
tipo. Não se está criando um novo tipo de dado apenas renomeando um já existente, isso 
pode ser útil para aumentar a portabilidade. Sua forma geral é: 
 
typedef tipo novo_nome; 
 
Em linguagem C toda linha de comando começando com # é uma diretiva do pré-
processador. 
 
#define nome_macro string substitui toda nome_macro que aparecer no código pela 
string, o nome da macro pode ter argumentos (macro semelhante a função): 
#define ABS(a) (a)<0? -(a) : (a) 
printf(“valor absoluto de –1 e %d”,ABS(-1)); 
#error mensagem pára a compilação e mostra a mensagem. 
#include <arquivo.h> instrui o compilador a ler o código no arquivo. 
#if #ifdef #ifndef #else #elif #endif permitem a compilação condicional de 
uma parte do código de acordo com uma condição/definição. 
 #if condição 
 comandos; 
 #endif 
#undef nome_macro remove a definição do nome da macro. 
defined nome_macro verifica se o nome damacro está definido. 
#line numero “nome_arquivo” estabelece novos __LINE__ e __FILE__. 
#pragma permite dar instruções ao compilador (consultar manual). 
 
O padrão C ANSI especifica cinco nomes intrínsecos de macros: 
 
__LINE__ número da linha atualmente sendo compilada. 
__FILE__ string com o nome do arquivo sendo compilado. 
__DATE__ data da tradução do arqivo fonte em código objeto, mm/dd/aa. 
__TIME__ hora da tradução do arqivo fonte em código objeto, h:m:s. 
__STDC__ booleana que indica se a implementação segue o padrão C ANSI.

Outros materiais