Buscar

computação básica

Esta é uma pré-visualização de arquivo. Entre para ver o arquivo original

computação básica/Apostila_ICC_Filomeno_Final.pdf
 
Página 1 de 75 
 
 
 
 
 
 
UNIVERSIDADE DE BRASILIA 
 
 
 
APOSTILA DE 
 
 
 
INTRODUÇÃO A CIÊNCIA DA COMPUTAÇÃO 
 
 
 
 
 
Prof: Luís Filomeno 
 
 
 
 
Brasília, 17 de Julho de 2009
 
Página 2 de 75 
 
Agradecimentos 
 
Gostaria de aproveitar a oportunidade para agradecer às seguintes 
pessoas e instituições pelo apoio ao longo do desenvolvimento 
deste trabalho. 
 
Gostaria de exprimir minha gratidão ao Prof. Jair Barbosa, meu 
colega de trabalho, enquanto trabalhador da UCB, meu sincero 
reconhecimento por sua competência e suas sugestões pertinentes. 
 
Igualmente, agradeço a todos os meus estudantes durante os anos 
que lecionei na Universidade Católica de Brasília - UCB pelas 
sugestões e interrogações que tornaram possível a concretização 
da presente apostila. 
 
 
Agradeço a Faculdade do Gama – Universidade de Brasília, por 
ter me concedido à oportunidade de desenvolver essa apostila. 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Página 3 de 75 
 
SUMÁRIO 
 
 
1 - INTRODUÇÃO............................................................................................................................1 
1.1 COMPILADORES E INTERPRETADORES ...........................................................................3 
1.2 ESTRUTURA BÁSICA DE UM PROGRAMA EM C ..............................................................3 
1.3 A LINGUAGEM C E A SENSIBILIDADE AOS CARACTERES............................................4 
1.4 ENTRADA E SAÍDA DE DADOS..............................................................................................4 
1.5 — CONSTANTES E VARIÁVEIS .............................................................................................6 
1.6 — TIPOS DE DADOS.................................................................................................................7 
1.7 — PALAVRAS-CHAVES (RESERVADAS) –...........................................................................8 
1.8 — COMENTÁRIOS ...................................................................................................................9 
2 - OPERADORES DA LINGUAGEM C......................................................................................10 
2.1 – OS OPERADORES ARITMÉTICOS ...................................................................................10 
2.2 — OPERADOR DE ATRIBUIÇÃO.........................................................................................10 
2.3 — OPERADORES RELACIONAIS ........................................................................................11 
2.4 — FUNÇÕES GETCH( ), GETCHE( ), GETCHAR( ) E PUTCHAR( ) ................................12 
2.5 — EXPRESSÕES ARITMÉTICAS..........................................................................................13 
2.6 — CÓDIGOS DE BARRA, TABELA DE TIPOS DE DADOS , CONVERSÃO DE TIPOS 
E CASTS. ........................................................................................................................................14 
3 — COMANDOS (ESTRUTURAS) DE CONTROLE DO PROGRAMA ..................................17 
3.1 — ESTRUTURAS DE SELEÇÃO............................................................................................17 
3.2 — A ESCADA IF-ELSE-IF ......................................................................................................19 
3.3 — OPERADOR CONDICIONAL OU ALTERNATIVO (?) OU TERNÁRIO ......................19 
3.4 — SELEÇÃO DE MÚLTIPLA ESCOLHA (SWITCH)..........................................................20 
4 — COMANDOS DE CONTROLE DO PROGRAMA ...............................................................21 
4.1 — O LAÇO FOR ......................................................................................................................21 
4.2 — O LAÇO WHILE .................................................................................................................23 
4.3 — O LAÇO DO-WHILE..........................................................................................................24 
4.4 — COMANDOS DE DESVIO ..................................................................................................24 
5 — FUNÇÕES ...............................................................................................................................27 
 
Página 4 de 75 
5.1 - INTRODUÇÃO.......................................................................................................................27 
5.2 — PASSAGEM DE PARÊMTROS ( POR VALOR E POR REFERÊNCIA) ......................31 
5.3 FUNÇÕES RECURSIVAS (OU DE RECORRÊNCIA) ..........................................................32 
5.4 — CLASSES DE ARMAZENAMENTO..................................................................................33 
6 – MATRIZES E STRINGS..........................................................................................................35 
6.1 — MATRIZES UNIDIMENSIONAIS......................................................................................35 
6.2 — MATRIZES COM DUAS OU MAIS DIMENSÕES ...........................................................37 
6.3 — MATRIZES COMO ARGUMENTOS DE FUNÇÕES.......................................................38 
6.4 — STRINGS E FUNÇÕES DE MANIPULAÇÃO...................................................................40 
6.5 — INICIALIZAÇÃO DE MATRIZES.....................................................................................43 
7 - PONTEIROS..............................................................................................................................45 
8 – ESTRUTURAS DE DADOS HETEROGÊNEAS ....................................................................49 
8.1 FORMA DE UMA ESTRUTURA EM C .................................................................................49 
8.2 – ACESSO AOS MEMBROS DE UMA ESTRUTURA E ATRIBUIÇÃO DE ESTRUTURAS49 
8.3 – MATRIZ DE ESTRUTURAS, ESTRUTURAS E ELEMENTOS (MEMBROS) DA 
 ESTRUTURA COMO ARGUMENTOS DE FUNÇÃO. ..............................................................51 
8.4 – CRIAÇÃO DE TIPOS DE DADOS. ......................................................................................52 
8.5 – MATRIZES E ESTRUTURAS DENTRO DE ESTRUTURAS ............................................53 
9 - ARMAZENAMENTO SECUNDÁRIO DE DADOS – ARQUIVOS.......................................54 
9.1 – OPERAÇÕES FUNDAMENTAIS COM ARQUIVOS.........................................................55 
9.2 DADOS NO FORMATO DE BLOCO OU REGISTRO .........................................................57 
9.3 LEITURA E ESCRITA DE CARACTERE A CARACTERE.................................................59 
9.4 LEITURA E ESCRITA DE CADEIA DE CARACTERES .....................................................59 
9.5 LEITURA E ESCRITA DE DADOS DE MODO FORMATADO ..........................................60 
10 - LISTAS DE EXERCÍCIOS .....................................................................................................62 
11- BIBLIOGRAFIA ......................................................................................................................71 
 
 
Página 1 de 75 
1 - Introdução 
 
Este curso visa os ensinamentos dos fundamentos da linguagem de programção C, que nas ultimas 
décadas tem ganho muito usuários principalmente devido a sua versatilidade em ser uma linguagem 
híbrida. A linguagem “C” ou apenas C tem sido caracterizado como uma linguagem assembler de 
alto nível (nível mais alto [Pascal, Cobol, Basic, Fortran]; nível
médio [C e C++, Forth]; nível 
mais baixo [Assembler]. Essa caracterização é devida ao fato de que o programador pode acessar 
os elementos internos do computador: bits, bytes e registradores que controlam a CPU e dispositivos 
externos. Desta maneira a linguagem de programação C caracteriza-se com uma linguagem de “nível 
alto” bem como uma linguagem de “nível baixo”. Deduz-se pela explanação anterior de que sistemas 
grandes e complexos podem ser construídos utilizando a linguagem C. 
Atualmente, em termos de aplicações em tempo real, a linguagem de programação C é a mais 
utilizada, desde a indústria passando pelas áreas de educação e pesquisa. Por isso a motivação na 
elaboração desta apostila e fornecer ao usuário um modo direto e simples de aprender a utilizar essa 
poderosa linguagem de programação. 
A linguagem C criada por Dennis Ritchie, na Bell Company na década de 70 do século passado, 
deriva da linguagem B, e inicialmente foi concebida para o sistema operacional UNIX. Atualmente 
versões da linguagem C são compatíveis com os diversos sistemas operacionais. 
Como referido anteriormente, o objetivo deste curso é de apresentar os conceitos fundamentais 
dessa linguagem de programação, que é rápida, impetuosa e eficiente. Para tal, pressupõe-se apenas 
familiaridade com os sistemas de computadores e conhecimento elementar de raciocínio lógico para 
acompanhamento e compreensão de alguns algoritmos implementados na linguagem C, apresentados 
nessa apostila. 
Dar-se-ão destaque as funções mais comuns e usuais dessa linguagem usados na maioria dos 
compiladores disponíveis. O enfoque será dado às instruções do C para o padrão ANSI. Ao leitor, 
recomenda-se fortemente a compreensão do compilador em que se esteja trabalhando, pois desta 
maneira poder-se-a entender as mensagens de avisos, mensagens de erros e possíveis bugs inerentes 
ao compilador, e/ou compilador-programa escrito pelo leitor. Reafirma-se que o domínio dessa 
linguagem não se restringe apenas aos conhecimentos de sua estrutural funcional, mas o 
conhecimento e compreensão do compilador em uso. 
Recomenda-se igualmente, que os programas exemplos mostrados sejam implementados, compilados 
e executados pelo usuário, visando a comprovação dos fundamentos apresentados. 
 
 
Página 2 de 75 
 
 
Página 3 de 75 
1.1 Compiladores e Interpretadores 
O processador inclui arquivos externos com fonte em C, se ele contiver diretivas #include. 
O compilador traduz a saída do pré-processador, em estágios, para um arquivo objeto – um arquivo 
OBJ – se não forem encontrados erros semânticos ou sintáticos. Se houver erros no código fonte C, 
o compilador apresenta uma lista deles com os respectivos números de linha em que ocorrem. O 
programador passa por um ciclo de edição/compilação até que todos os erros sintáticos e semânticos 
sejam eliminados. 
O ligador une o arquivo-objeto produzido pelo compilador aos arquivos apropriados da biblioteca e 
eventualmente a outros a outros arquivos-objetos. O arquivo resultante é um .EXE que pode ser 
executado pela máquina. 
 
1 – Criar o programa 
2 – Compilar o programa Compilando um programa em C 3 – Linkeditar o programa com as funções necessárias de 
bibliotecas. 
 1.2 Estrutura Básica de um Programa em C 
 
A unidade fundamental de programas em C são as funções, ou seja, em C qualquer programa é 
estruturado com base em funções. Um programa pode ter várias funções quantas o leitor quiser. A 
seguir apresenta-se a explicitação de uma função em C. 
Função básica: 
tipo nome ( ) 
{ 
 variável; void main(void) 
 instrução_1; { 
 . variável; 
 . instrução; 
 . } 
 instrução_2; 
} 
 
Em todo o programa em C deve existir uma única função chamada main, que indica a inicialização 
da execução do programa. Geralmente essa função é do tipo void, mas alguns compiladores 
requerem uma declaração do tipo int. 
 
 
Página 4 de 75 
O programa termina quando esteja encerrada a execução da função main. A função é atrás descrita é 
do tipo void que significa que ela não tem valor de um return, isto é, não retorna nada. Por outro 
lado, se a função for do tipo int, deverá ter no final do mesmo a palavra return seguido de um valor 
inteiro, ex: return (0). 
1.3 A linguagem C e a sensibilidade aos caracteres 
Uma das particularidades da linguagem C é que a mesma é “sensível” aos caracteres maiúsculos e 
minúsculos. Existe diferença entre escrever alguma variável com letras maiúsculas e minúsculas, pois 
elas são diferentes embora possuam os mesmos caracteres ou letras. Para fins exemplificativos, 
declaramos uma variável de nome multa. Os exemplos a seguir de MULTA, mUlTa, MuLtA etc, 
serão interpretados pelo compilador com três variáveis diferentes embora sejam composta pelos 
mesmos caracteres. Em C os comandos ou também ditas instruções são sempre escritas com 
caracteres minúsculos, tais com auto, break, case, if, for, while etc. Sempre que uma destas ou 
outras palavras reservadas forem utilizadas com caracteres maiúsculos serão interpretados pelo 
compilador com variáveis em vez de palavras ou comando do C. 
1.4 Entrada e saída de dados 
Em qualquer sistema de computação existe a interação do usuário e o computador para leitura e 
escrita de dados, que poderá ser feita através do teclado, drivers de entrada e de saída, arquivo e 
impressoras. Na linguagem C existem algumas funções para entrada e saída de dados que 
apresentaremos a seguir. 
 
1.4.1 Função printf: Saída no Terminal 
Em programação é fundamental gravar saídas em arquivos e em terminais de saída ou monitor. Uma 
das mais úteis e versáteis funções de saída é printf. Esta função é implementada na biblioteca externa 
<stdio.h>. 
A função printf pode ser usada para dar saída a qualquer combinação de caracteres, inteiros, reais, 
cadeias, inteiros sem sinal, inteiros longos e inteiros longos sem sinal. 
Uma chamada típica de printf é a seguinte: 
 printf (“\nA idade de João é %d. Sua renda é R$ %5.2f”, idade, renda) 
 
Presume-se que à variável inteira idade e à variável real renda tenham sido atribuídos valores. 
A combinação barra invertida \n – leva o cursor para a linha seguinte. A cadeia literal A idade de 
João é exibida a partir da nova linha. O %d é um marcador de lugar para uma variável inteira. O 
 
 
Página 5 de 75 
valor da variável “idade” é usado em lugar do %d. O literal Sua renda é vem a seguir. O %5.2f é 
um marcador de lugar (caracter de conversão de formato) para um valor real, bem como uma 
instrução de formato para incluir apenas duas casas decimais. 
Mais finalmente, os marcadores de lugar são definidos da seguinte forma: 
 
% [largura] [.precisão] [indicadores] [I,L] excluir 
 
I, L – são usados para tipos inteiros longos 
largura – tamanho mínimo, em caracteres, do campo a exibir 
 
Exemplo: Número real de dez posições, dos quais inclui 5 números correspondem a parte inteira e 4 
números a parte real, ou seja ficam após a virgula. 
 
%10.4f 
 
 
Tipo de Conversão Significado da Precisão 
inteiro quantidade de dígitos 
real dígitos após o ponto decimal 
cadeia quantidade de caracteres 
 
Caracter 
de Conversão Tipo de Objeto 
%c char (caractere) 
%s matriz de char (ou matriz de caracteres) 
%d int 
%o int (octal) 
%u int sem sinal 
%x int (hexadecimal) 
%ld long (decimal) 
%lo long (octal) 
%lu unsigned long 
%lx long (octal) 
%f float/double (ponto fixo) 
%e float/double (exponencial)
%g float/double (o menor entre os formatos f ou e) 
%lf long float (ponto fixo) 
%le long float (exponencial) 
%lg long float (o menor entre os formatos f ou e) 
 
 
 
 
 
1.4.2 Função scanf: Entrada a partir do teclado 
 
 
Página 6 de 75 
A instrução scanf é uma das muitas funções de entrada (pelo teclado) presente nas bibliotecas 
externas (stdio.h). Para cada variável de entrada é necessário colocar um marcador de lugar. O 
sinal epersete, &, deve ser usado na frente de cada variável de entrada. Este símbolo significa “o 
endereço de”. Mais adiante quando apresentarmos o conceito de ponteiros, retornaremos a esse 
operador. 
 scanf(“%d”, &palavra); 
Não é recomendável a especificação de números de digitos a serem lidos, pois isso restringe a leitura 
da variável e pode ocasionar erros. Se por ex: scanf(“%2d”, &valor); e fosse digitado 1987, o 
endereço guardaria apenas o digito 87 e perderia 19. No item 2.4 nos referiremos a outras funções 
de leitura de caracteres. 
1.5 — Constantes e Variáveis 
Tal como nas demais linguagens de computação, em C também manuseiam-se dois tipos de dados: 
constantes e variáveis. 
Constantes – são valores fixos ou predefinidos e uma vez atribuídos, permanecem inalteráveis 
durante a execução de qualquer programa. As constantes podem ser numéricas, lógicas e literais. 
Eles são da forma decimal, hexadecimal, octal e caractere. 
Ex.: Constante caracter 
 
82, 0x41, 0754, ‘A’ 
Ex. const int a=9; float alfa= 3.15; char beta=’C’ 
 
Variáveis - é um espaço de memória reservado para armazenar certo tipo de dado e tendo um nome 
para referenciar o seu conteúdo. Este espaço de memória ocupado por uma variável pode ser 
compartilhado por diferentes valores segundo certas circunstâncias. 
Uma declaração de variável consiste no nome de um tipo, seguido do nome da variável, 
seguida de ponto-e-vírgula. Ex: float x, y; int a; char letra; 
As variáveis devem ser declaradas antes de serem usadas no programa. Uma variável pode ser 
declarada em qualquer ponto do programa. 
Tipo de variável refere-se sempre ao tamanho de memória e à forma de armazenamento. 
Os tipos de variáveis quanto ao tamanho: 
Tipo Bit Bytes 
char 8 1 
 
 
Página 7 de 75 
int 16 2 
float 32 4 
double 64 8 
void 0 0 
 
De acordo com o uso das variáveis no programa elas podem ser de dois tipos: locais e globais. 
As locais são declaradas no interior de uma função, as globais são declaradas fora de uma 
função. Essas são visíveis (isto é, podem ser acessadas) em qualquer lugar do arquivo (módulo) na 
qual são definidas. 
/* Arquivo primeiro.c */ 
void main (void) 
{ 
 extern int a, b; 
 printf (“\n a=%d b=%d\n”, a, b); 
 float y= 3,14; 
 printf (“\n y=%f \n”, y); 
} 
 
/* Arquivo segundo.c */ 
 int chama 
 int a=2; 
 b=5; 
 Neste caso a=2 e b=5, foram declaradas fora do programa principal, logo são externas, e funcionam 
como variáveis globais. Ao contrario, a variável y foi declarada no escopo do programa principal, 
assim, ela é vista como uma variável local. No estudo de funções, abordaremos com maior 
profundidade os conceitos de variáveis locais e globais. 
1.6 — Tipos de Dados 
Um tipo é constituído por um conjunto de valores e um conjunto de operações que podem ser 
executadas com as variáveis de tal tipo. 
O C tem muitos tipos de dados predefinidos, os escalares mais simples (char, int, long, float, 
double e outros que apresentaremos mais tarde como (Ponteiros, Enumeração, Matriz, Estrutura, 
 
 
Página 8 de 75 
União – tipos agregados –, Função e Vazio – que não pode assumir valores nem participar de 
operações.) 
Tipos escalares de informação processada pelo computador: 
• caractere (char): sequência contendo letras, números e símbolos especiais (caracteres 
alfanuméricos) 
– essa sequência deve ser indicada entre aspas (“ “) 
– Exemplo: “Gama - DF”, “356-9025”, “CEP-72140-000” 
– também chamado de string ou cadeia de caracteres. 
– Para um caractere indica-se (’’) 
• inteiro (int): toda informação numérica inteira (não fracionária) negativa, nula ou positiva. 
Exemplo: -50, 130, 0, 73 
• real (float): toda informação numérica pertencente ao conjunto dos números reais (inteiros 
ou fracionários), (negativa, nula ou positiva). Exemplo: 12, 0, -3, 1.7, 101.5, 4.0 = símbolo 
de ponto 
• double (double): informação na forma de número reais mas com número de dígitos maiores. 
• Logico: conjunto de valores - falso ou verdadeiro 
– Esse tipo só apresenta um desses valores (excludentes) 
– também chamado de booleano. 
 
1.7 — Palavras-Chaves (Reservadas) – ANSI 
Existem várias entidades americanas que definem padrões para a indústria e informática, tais como 
ANSI, ANSII, etc. Pela padronização ANSI existem algumas palavras chamadas reservadas ou 
chaves que não podem ser usadas como identificadores e nem como funções. O compilador é 
sensível as diferenças entre letras maiúsculas e minúsculas. As palavras apresentadas na tabela abaixo 
jamais poderão ser utilizadas a não ser para o propósito especifico definido em C. 
 
asm default for pascal switch 
auto do goto register typedef 
break double huge return union 
case else if short unsigned 
cdecl enum int signed void 
char extern interrupt sizeof volatile 
 
 
Página 9 de 75 
const for long static while 
continue float mean struct 
 
1.8 — Comentários 
Os comentários geralmente destinam-se a documentar e depurar o código. São usados de modo a 
ajudar no esclarecimento e compreensão do código. 
Textos delimitados pelo símbolo /* e */ são ignorados pelo compilador e representam a maneira mais 
geral de escreverem-se comentários em C. 
A grande maioria dos compiladores atuais permite que se utilize o mesmo compilador para escrever, 
compilar e executar tanto códigos escritos em C como em C++. Assim é usual encontrar-se 
programas escritos em C, mas que usam comentários do C++. 
Resumindo, os comentários abaixo costumam ser aceites em C. 
Ex: /* Isso é um comentário em C*/ 
 // Isso é um comentário em C++, mas alguns compiladores o reconhecem. 
 
 
Página 10 de 75 
 
2 - Operadores da Linguagem C 
Na linguagem de programação C contempla os seguintes tipos de operadores: aritméticos, de 
atribuição, aritméticos de atribuição, relacionais e lógicos. Nas próximas seções apresentam-se esses 
operadores. 
2.1 – Os Operadores Aritméticos 
São os sinais de adição (+), subtração (–), divisão ( / ), multiplicação (*) e resto (%). Exceto o 
operador resto, que não está definido para variáveis de tipo real, todos os outros estão definidos para 
os tipos inteiros, caracteres e reais. 
Alguns destes operadores são unários e outros binários. Os unários agem sobre uma variável apenas, 
modificando ou não o seu valor, e retornam o valor final da variável. Os binários (ex. soma, 
multiplicação, divisão, subtração e resto da divisão) usam duas variáveis e retornam um terceiro 
valor, sem alterar as variáveis originais, desde que o resultado seja colocado numa terceira variável. 
Por exemplo, o produto (ou multiplicação) é um operador binário, pois usa duas variáveis, multiplica 
os valores dos operandos, sem alterar as variáveis, e fornece o valor final do produto numa outra 
variável. 
 
2.2 — Operador de Atribuição 
O operador de atribuição (=), e consiste na atribuição na variável a esquerda
do valor ou endereço 
da variável da direita. 
Ex.: j=2; y=x; a=b+c; 
 
2.2.1 — Operadores de Atribuição Aritméticos 
São os operadores derivados da junção dos operadores aritméticos e de atribuição, ou seja, (+=, – 
=, *= e /=). Todos atribuem o resultado de uma expressão a uma variável. 
Se o tipo do lado esquerdo da atribuição não for o mesmo que o do lado direito, o tipo do lado 
direito será convertido para o tipo do lado esquerdo. 
Exemplos: 
a+=b  a=a+b 
a–=b  a=a–b 
a*=(b+c)  a=a*(b+c) 
 
 
Página 11 de 75 
a/=(b–c)  a=a/(b–c) 
 
Os operadores pós-fixados e prefixados, ++ e ––, são usados para incrementar e decrementar uma 
variável. O significado de cada um deles é o seguinte: 
++x – incrementa de um a variável x, antes de usar seu valor em uma expressão. 
x++ – incrementa de um a variável x, após usar seu valor em uma expressão. 
--x – decrementa de um a variável x, antes de usar seu valor em uma expressão. 
x-- – decrementa de um a variável x, após usar seu valor em uma expressão. 
 
 
Exemplos.: a=4; b=++a; o resultado é b=5 
 a=4; b=a++; o resultado é b=4 
 a=7; c=--a; o resultado é c=6 
 a=7; c=a--; o resultado é c=7 
2.3 — Operadores Relacionais 
Os operadores relacionais são o teste de igualdade (==), teste de desigualdade(!=) menor que(<), 
menor do que ou igual(<=), maior que(>), maior do que ou igual (>=). 
Todos os operadores relacionais retornam um inteiro. O valor do inteiro é um (1) se a relação 
entre os operandos é verdadeira, e zero (0) se a relação entre os operandos for falsa. 
 
2.3.1 — Operadores Lógicos 
O conceito de operador lógico provém da área dos circuitos eletrônicos, e seu conceito é similar ao 
príncipio de funcionamento das portas lógicas. Assim têm-se três (3) operadores lógicos que são: 
interseção, união e negação. A tabela-verdade correspondente a esses operadores mostra-se a 
abaixo: 
A B A e B A ou B negação A 
0 0 0 0 1 
0 1 0 1 1 
1 0 0 1 0 
1 1 1 1 0 
 
Esses operadores quando utilizados na linguagem C adotam a seguinte representação: 
&& - operador e (interseção) 
| | - operador ou (união) 
 ! – negação. 
 
 
Página 12 de 75 
 
 
Os operadores lógicos podem receber qualquer tipo de argumento numérico, incluindo caracter, e 
retornar um para verdadeiro, ou zero para falso. 
A avaliação de uma expressão envolvendo operadores lógicos procede da esquerda para a direita tão 
logo o resultado possa ser determinado. 
Ex.: i=4; j=4; 
if ((i>5) && (j==4)) 
o resultado desta operação é 0 (falso) pois 4 é menor que 5 (falso) e 4 igual a 4 (verdadeiro). Para 
ser verdadeiro as duas operações relacionais deveriam ser verdadeiras, o que não é. 
 
2.3.2 — Operadores de caracteres 
Em C existe o operador de concatenação (+) que é aplicável apenas as variáveis do tipo caractere. 
Permite a concatenação de caracteres, cuja interpretação seria aglutinar ou juntar caractere(s) a 
outro(s). 
2.4 — Funções getch( ), getche( ), getchar( ) e putchar( ) 
Além da função de leitura de dados scanf() que permite ler todos os tipos de dados escalares, tais 
como char, int, float, double, existem também algumas funções especificas para leitura e escrita 
apenas de um (1) caractere, tais funções pertencem a arquivo cabeçalho ou biblioteca <conio.h>. 
Eis o mnemônico destas funções: 
getch () – lê um caractere a partir do teclado mas não o mostra na tela; 
 
getche () – lê um caractere a partir do teclado e mostra-o na tela; 
 
getchar () – lê um caractere a partir do teclado mas não o mostra na tela; 
 
putchar () – escreve um caractere mostrando-o na tela; 
 
Ex: option = getch(); -> o caractere lido é atribuído a variável option; 
 
 option = getche(); -> o caractere lido é atribuído a variável option e mostrado na tela; 
 
Ex: do { 
 printf(“1: Entrada dados\n”); 
 printf(“2: Altera dados\n”); 
 printf(“3: Sair\n”); 
 escolha=getch( ); 
 
 
Página 13 de 75 
 ch=getche( ); 
 } while ((ch!=1) &&(ch!=2)&&(ch!=3)); 
2.5 — Expressões aritméticas 
Operadores, constantes e variáveis são os elementos que constituem as expressões. Uma expressão 
em C é qualquer combinação válida desses elementos. Uma vez que a maioria das expressões tende a 
seguir as regras gerais da álgebra, elas são freqüentemente tomadas como certas. Nas expressões 
devem ser usadas apenas variáveis numéricas, operadores aritméticos e funções matemáticas pré-
definidas, tais como, por exemplo: sin(x), sqrt(t), abs(x) etc. 
Ex: x= 3*5+4; 
 
 y = x+6%2+3.28; 
 
 z= y*y; 
 
Deve-se prestar atenção a procedência dos operadores, pois alguns operadores têm ordem de 
procedência maior que outros. Para evitar possíveis erros faça uso sempre de parênteses. 
Ex: 9+4*5  (9+4)*5 
 3+9/6  (3+9)/6 
Se tentarmos estabelecer uma ordem de precedência geral aplicável a linguagem de programação C 
esta deverá ser a seguinte: 
1) Funções e parêntesis 
2) Expressões aritméticas 
 +, - (unitários) 
 *, /, % 
 +, - (binários) 
3) Comparações 
 <, <=, == , >= , >, != 
4) Não, inversora, ou negação 
5) Conjunção ou e 
6) Disjunção ou também dita ou. 
 
 
 
 
 
 
 
 
Página 14 de 75 
2.6 — Códigos de barra, tabela de tipos de dados, conversão de tipos e 
casts. 
C suporta diversos códigos de barra invertida (listados na tabela abaixo) e de forma 
que você pode facilmente entrar esses caracteres especiais como constantes, e usá-los em conjunto 
com diretivas de impressão. 
Código Significado 
\b Retrocesso 
\f Alimentação de formulário 
\n Nova linha 
\r Retorno de carro 
\t Tabulação horizontal 
\” Aspas duplas 
\’ Aspas simples 
\0 Nulo 
\\ Barra invertida 
\v Tabulação vertical 
\a Alerta (beep) 
\N Constante octal 
\xN Constante hexadecimal 
 
2.6.1- Conversões de tipos 
Em programação é comum existirem expressões em que variáveis de um tipo são misturadas com 
variáveis de outro tipo. Para compreender o principio de conversão na atribuição e nas expressões 
apresenta-se a seguir a tabela dos tipos definidos pelo padrão ANSI. Constam dessa tabela o tipo de 
dados e a quantidade de dígitos necessários para representá-los. Com isso torna-se mais fácil 
compreender as operações de conversão entre diferentes tipos. 
 
Tabela de todos os tipos de dados definidos pelo padrão ANSI 
Tipo Tamanho em Bits Tamanho em Bytes 
char, unsigned char, signed char 8 1 
int, unsigned int, signed int, short int 16 2 
long int, signed long int, float 32 4 
double 64 8 
 
 
2.6.1.1 Conversão de tipos em atribuições 
Em um comando de atribuição, a regra de conversão de tipos é muito simples: o 
valor do lado direito (o lado da expressão) de uma atribuição é convertido no tipo do lado 
esquerdo (a variável destino). 
Deve-se prestar atenção para atribuições de tipos em que a variável destino requer menos bits que a 
variável a direita da expressão. Neste caso, embora o processo de atribuição seja possa efetuado, 
 
 
Página 15 de 75 
nem sempre se tem a certeza de que dados da variável a direita, foram armazenados na variável 
destino. 
Ex: int a=5; double z= 3,14196; 
 a=z; 
Esse processo de atribuição, certamente não gerará mensagem de erro, mas conceitualmente está 
errado, pois como
a quantidade de bits de um número double são 64 e de um número int são 16 
bits. O compilador não entenderá se atribui os 16 bits mais significativos ou os 16 bits menos 
significativos. È perrogativa de o programador instruir o compilador a fazer a atribuição correta. 
 
Conversão de Tipos em Expressões 
Quando constantes e variáveis de tipos deficientes são misturadas em uma expressão elas são 
convertidas a um mesmo tipo. O compilador C converte todos os operandos no tipo de maior 
operando, o que é denominado promoção de tipo, como descrito nas regras de conversão de tipo 
abaixo. 
Se um operando é long double, então o 2º é convertido em long double, senão 
Se um operando é double, então o 2º é convertido em double, senão 
Se um operando é float, então o 2º é convertido em float, senão 
Se um operando é unsigned long, então o 2º é convertido em unsigned long, senão 
Se um operando é long, então o 2º é convertido em long, senão 
Se um operando é unsigned int, então o 2º é convertido em unsigned int, senão. 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
resultado = (ch / i) + (f * d) - (f + i)
int floatdouble
int double
double
 
 
Página 16 de 75 
2.6.1.2 Cast (modelador) 
 
Cast (ou modelador) aplicam-se as expressões. Visam forçar uma expressão a ser de um 
determinado tipo. A forma genérica de um cast é: 
 
 (tipo) expressão; onde tipo é qualquer tipo de dados em C. 
 
Ex: No programa abaixo força-se a um resultado do tipo inteiro a ser um resultado real. 
#include <stdio.h> 
Void main(void) 
{ int a =60 ; float b1, b2; 
 b1=(float )a/13; 
 b2=(float )a*2,0; 
 printf(“os resultados são %f e %f\n”,b1,b2); 
} 
No programa acima anterior, se o uso da cast o programa faria a divisão de números inteiros entre 
60 e 13, que resulta em 4 e converteria posteriormente para real, e daria 4,0. Com o uso da cast, a 
divisão entre 60 e 3, resulta no valor correto de 4,615. Na multiplicação, fará o produto entre os 
inteiros 60 e 2, e posterioremente fará a conversão para o número real 120,0. 
 
 
 
 
 
 
 
 
 
 
 
 
Página 17 de 75 
3 — Comandos (Estruturas) de controle do programa 
Dos conceitos apresentados até o momento percebe-se que a execução de um programa em C ocorre 
de cima para baixo, ou seja, em ordem seqüencial de execução de instrução após instrução. Ocorre 
que as linguagens de programação modernas possuem comandos que permitem a execução de 
condições, saltos e/ou repetições, chamados de comandos de controle de fluxo ou de programa. Na 
linguagem de programação C os comandos de controle dividem-se em seqüências, de selecção (ou 
condicional) e de repetição (looping). O uso destes comandos depende da natureza do problema a 
ser sistematizado através de um programa. Em algumas situações usam-se apenas alguns comando, 
em programas mais complexos e normal o uso de todos os comandos de controle. 
 
 
3.1 — Estruturas de Seleção 
 
Do ponto de vista conceitual, estas estruturas aplicam-se quando dependendo de uma avaliação 
condicional, realizada mediante lógica convencional na forma de expressões lógicas, como 
conseqüência, uma instrução ou um conjunto de instruções selecionadas deve ser executado. 
A Linguagem de Computação C suporta dois tipos de comandos de seleção: if e switch. Além 
disso, o operador ? (chamado operador ternário) é uma alternativa ao if em certas circunstâncias. 
 
3.1.1 — if 
Essa estrutura de seleção pode ser implementada na forma simples, composta ou incadeada. 
Linguagem de Computação C suporta dois tipos de comandos de seleção: if e switch. Além disso, o 
operador ? (chamado operador ternário) é uma alternativa ao if em certas circunstâncias. 
A forma da sentença if é no modo simples: 
 if(expressão) comando; 
 
A forma geral da sentença if ou forma composta é: 
 if(expressão) comando; 
 else comando; 
 
onde o comando pode ser uma única instrução ou um bloco com várias instruções ou nada (no caso 
de comandos vazios). 
 
 
Página 18 de 75 
Se a expressão é verdadeira (diferente de zero), o comando ou bloco que forma o corpo do if é 
executado; caso contrário; o comando ou bloco que é o corpo do else (se existir) é executado. 
Lembre-se que o código associado ao if ou código do else será executado, nunca ambos. 
O comando condicional controlando o if deve produzir um resultado escalar. Um escalar é um 
inteiro, um caractere, é raro usar um número ponto flutuante (real) para controlar uma 
expressão condicional. 
 
3.1.2 — IF’s Aninhados 
Um if aninhado é um comando if que é o objeto de outro if ou else. If’s aninhados são muito 
comuns em programação. Em C, um comando else sempre se refere ao comando if mais próximo, 
que está dentro do mesmo bloco do else e não está associado a outro if. 
Ex.: 
 int a=4, b=3, c=4; 
 if (a<2) 
{ 
 if (b==5) comando 1; 
 if (c>8) comando 2; /* este if */ 
 else comando 3; /* está associado a este else */ 
 } 
 else comando 4; /* associado ao if (a<2) */ 
No exemplo anterior, quando efetua-se o primeiro teste, como a=4 e 4 não é menor que 2, então 
nesse caso executa-se o comando 4, que corresponde a condição falsa do teste efetuado com (a<2). 
O padrão C ANSI especifica que pelo menos 15 níveis de aninhamento devem ser suportados. 
 
Ex.: 
#include<stdio.h> 
void main(void) 
{ 
int i=4, j=6, k = 8; 
 if (i<k) 
 { 
 if (i>j) printf(“Instrução1\n”); 
 else printf(“Instrução2\n”); 
 } 
} 
 
O programa anterior está correto e imprime “Instrução 2”. 
 
 
 
 
 
Página 19 de 75 
3.2 — A escada if-else-if 
A sua forma geral é dada por: 
 
 
 if (expressão) 
 comando; 
 else if (expressão) 
 comando; 
 . 
 . 
 . 
 else comando; 
 
 
As condições são avaliadas de cima para baixo. Assim que uma condição verdadeira é 
encontrada, o comando associado é executado e desvia do resto da escada. Se nenhuma das 
condições for verdadeira então o último else é executado. Se o último else não está presente, 
nenhuma ação ocorre se todas as condições são falsas. 
 
 
3.3 — Operador Condicional ou Alternativo (?) ou Ternário 
O operador condicional (?) pode ser usado para substituir comandos if-else na forma geral. 
 
 if (condição) expressão; 
 else expressão; 
 
Os corpos do if e else devem ser uma expressão simples, nunca um outro comando de C. 
O operador ? é chamado de operador ternário, porque requer três operandos, e tem a seguinte 
forma geral: 
 
 expressão1?expressão2:expressão3 
 
 
A interpretção da forma anterior é a seguinte: o valor de uma expressão ? é determinada como 
segue: expressão1 é avaliada, se for verdadeira, expressão 2 será avaliada e se tornará o valor da 
expressão ? inteira. Se expressão1 é falsa, então expressão 3 é avaliada e se torna o valor da 
expressão. 
Ex.: 
 
 #include <stdio.h> 
 void main(void) 
{ 
 int i=6, 
 j=4; 
 int resultado=(i<j)? i : j; 
 printf (“%dn”, resultado); 
x=15 
z=(x<30)?40:60; 
 
similar a: 
x=15 
if (x<30) z=40 
else z=60 
#include <stdio.h> 
void main(void) 
{ 
int i=6, quadrado; 
quadrado=i>0?i*i:-(i*i) 
printf(“%d ao quadrado é %d”, 
i, quadrado); 
} 
 
 
Página 20 de 75 
} 
 
 
3.4 — Seleção de múltipla escolha (switch) 
Utiliza-se essa estrutura de seleção quando uma determinada variável pode ser igual a diferentes 
valores
que se deseja avaliar. 
switch (<valor>) 
{ 
 case v1 
 comandos 1; break; 
 case v2, v3 
 comandos 2; break; 
 case v4 
 comandos 3; break; 
 default: 
 comandos 4; 
 } 
 
Para muita gente os comandos break são opcionais, dentro do switch. Eles terminam a seqüência de 
comandos associados com cada constante. Se o comando break é omitido, a execução continua 
pelos próximos comandos case até que um break, ou fim do switch, seja encontrado. O teste 
condicional da instrução de múltipla escolha não usa os operadores relacionais, pois só realiza a 
operação de igualdade, como se mostra no exemplo abaixo: 
 
Ex.: 
 void main(void) 
 { 
 char ch; 
 printf (“1. Soma \n”); 
 printf (“2. Multiplicação\n”); 
 printf (“3. Divisão\n”); 
 printf (“4. Subtracão\n”); 
 printf (“Pressione Qualquer Outra Tecla para Abandonar\n”); 
 printf (“ Entre com sua Escolha ”); 
 ch=getchar( ); /* Lê do Teclado a Seleção */ 
 switch(ch) { 
 case ‘1’: 
 Soma( ); 
 break; 
 case ‘2’: 
 Multiplica( ); 
 break; 
 case ‘3’: 
 Divisao( ); 
 break; 
 case ‘4’: 
 Subtracao( ); 
 
 
Página 21 de 75 
 break; 
 default: 
 printf(“Nenhum Opção Selecionada”); } 
 } 
4 — Comandos de controle do programa 
Em todas as linguagens modernas de programação, comandos de iteração (também chamados de 
laços) permitem que um conjunto de instruções seja executado até que ocorra uma certa condição. 
Essa condição pode ser predefinida (como no laço for) ou com final em aberto (como nos laços 
while e do-while). 
 
4.1 — O Laço FOR 
Este comando é encontrado em todas as linguagens de programação, contudo em C, ele fornece a 
flexibilidade e capacidades surpreendentes. 
A forma geral do comando for é: 
 
for(inicialização; condição; incremento) comando; 
 
 
O laço for permite várias variações. A inicialização é geralmente um comando de atribuição que é 
usado para colocar um valor na variável de controle do laço. A condição é uma expressão relacional 
que determina quando o laço acaba. O incremento define como a variável de controle do laço varia 
cada vez que o laço é repetido. 
Uma vez que a condição se torne falsa, a execução do programa continua no comando seguinte ao 
for. 
Ex.: Este programa imprime os números de 1 a 50 na tela: 
 
 #include <stdio.h> 
 void main(void) 
 { 
 int x; 
 for(x=1;x<=50;x++) printf(“%d”,x); 
 } 
 
 
No programa x é inicialmente 1, uma vez que x é menor do que 50, printf( ) é executado e x é 
incrementado em 1 e testado para ver se ainda é menor ou igual a 50. Este processo se repete até 
que x fique maior que 50, nesse caso, o laço (ciclo) termina. 
 
 
 
 
 
Página 22 de 75 
 
 
Ex.: Laço for com múltiplos comandos: 
 
 #include <stdio.h> 
 void main(void) 
 { 
 int x; float z; 
 for(x=100;x!=65;x-=5) 
 { 
 z=x*x; 
 printf(“O quadrado de %d é %f”,x,z); 
 } 
 } 
 
Neste caso a multiplicação de x por si mesmo, como a função printf( ) são executados até que x seja 
igual a 65. Repare que o laço é executado de forma inversa: x é inicializado com 100 e será 
subtraído de 5 cada vez que o laço se repetir. 
Nos ciclos de repetição for o teste condicional sempre é executado no topo do laço. Isso significa 
que o código dentro do laço pode não ser executado se todas as condições forem falsas logo no 
início, atente ao exemplo a seguir. 
Ex.: 
 
 x=10; 
 for (y=10;y!=x;++y) printf(“%d”,y); 
 printf(“%d”, y); /* Este é o único comando printf( ) que será executado */ 
 
Como x e y são iguais desde a sua entrada. o laço nunca executa. Já a expressão condicional é 
avaliada como falsa, nem o corpo do laço nem a porção do incremento são executados. 
 
4.1.1 — Variações do laço FOR 
 
Uma das variações mais comum usa o operador vírgula para permitir que duas ou 
mais variáveis controlem o laço. Lembra que o operador vírgula é usado para encadear expressões 
numa configuração “faça isso e isso”. 
Ex.: 
 
 #include <stdio.h> /* Este programa não está completo, logo não funciona */ 
 void main(void) 
 { 
 int x, z, y, w; 
 for(x=0,y=0;x+y<10;++x,y++) 
 { 
 z=y+x; 
 w= y-x; 
 . 
 . 
 
 
Página 23 de 75 
 . 
 } 
 } 
 
 
4.1.2 — O Laço infinito 
 
Já que nenhuma das três expressões que formam o laço for é obrigatória, você pode fazer um laço 
sem fim, deixando a expressão condicional vazia, como aqui: 
 
for(; ;) printf(“Esse comando será executado para sempre.\n”); 
 
 
4.2 — O Laço WHILE 
O segundo laço disponível em C é o laço while. A sua forma geral é: 
 
while(condição) comando; 
 
Onde comando é um comando vazio, um comando simples ou um bloco de comandos. A condição 
pode ser qualquer expressão, é verdadeiro é qualquer valor diferente de zero. O laço se repete 
quando a condição for verdadeira. Quando a condição for falsa, o controle do programa passa 
para a linha após o código do laço. 
Ex.: O programa abaixo mostra um controle pelo teclado, que simplesmente se repete até que o 
usuário digite A ou a: 
 
 void main(void) 
 { 
 char ch; 
 ch=’\o’; /* Inicializa */ 
 while((ch!=’A’)&&(ch!=’a’)) 
 { 
 ch=getchar( ); 
 printf(“%c”, ch); 
 } 
 } 
 
 
Inicialmente, ch é inicializado com nulo. O laço while verifica se o ch não é igual a A ou a. Como ch 
foi inicializado como nulo, o teste é verdadeiro e o laço começa. Uma vez digitado A ou a, a 
condição se torna falsa, porque ch fica igual a A ou a e o laço termina. 
Os laços while verificam a condição de teste no início do laço, o que significa que o código do laço 
pode ser executado. Isso elimina a necessidade de se efetuar um teste condicional antes do laço. O 
controle pode ser feito pelo usuário ou por intermédio de uma variável contadora. 
 
 
 
Página 24 de 75 
 
4.3 — O Laço DO-WHILE 
 
Este laço difere dos laços for e while, pois nestes a condição do laço é testada no inicio do laço, 
enquanto que no laço do-while o teste condicional de verificação é efetuado no final do laço. Isso 
significa que o laço sempre será executado ao menos uma vez. 
A forma geral do laço do-while é: 
 
do { 
 comando; 
} while (condição); 
 
Embora as chaves não sejam necessárias quando apenas um comando está presente, elas são 
geralmente usadas para evitar confusão para usuário com o while. O laço do-while repete até que a 
condição se torne falsa. Este tipo de ciclo de repetição é geralmente utilizado para validação de 
variáveis, ou seja, usa-se repetitivamente até que as variáveis recebam apenas os valores aceitáveis. 
Ex: Código de validação de variáveis inteiras positivas. 
 int x; 
do { 
 printf(“Digite o valor de x: x >=0\n”); 
 scanf(“%d”, &x); 
 } while (x<0); 
 
 
Ex.: O seguinte programa (laço do-while) lerá números do teclado até que se encontre um número 
menor ou igual a 100. 
 
 
 #include <stdio.h> 
 void main(void) 
 { 
 int num; 
 do { 
 scanf(“%d”, &num); 
 } while (num>100); 
 } 
 
 
4.4 — Comandos de Desvio 
 
Na linguagem C existem quatro comandos que realizam um desvio incondicional: return, goto, 
break e continue. Esses comandos são apresentados nas subseções abaixo. 
 
 
Página
25 de 75 
 
4.4.1 — O Comando RETURN 
O comando return é usado para retornar de uma função. Ele é um comando de desvio porque faz 
com que a execução retorne (salte de volta) ao ponto em que a chamada da função foi feita. Se 
return tem um valor associado a ele, esse valor é o retorno da função. Se nenhum valor for 
especificado para retorno, assume-se apenas lixo é retornado (alguns compiladores em C irão 
automaticamente retornar se nenhum valor foi especificado, mas não conte com isso!). 
A forma geral do comando return é: 
 
return expressão; 
 
Lembre-se de que a expressão é opcional. Entretanto, se estiver presente, ela se tornará o valor da 
função. 
Você pode usar quantos comandos return quiser dentro de uma função, contudo a função cessará de 
executar tão logo ela encontre o primeiro return. A chave (}) que finaliza uma função faz com que a 
função retorne. É o mesmo que return sem nenhum valor especificado. 
4.4.2 — O Comando GOTO 
 
Não existe nenhuma situação na programação que necessite do goto. Contudo goto é uma 
conveniência que, se usada prudentemente pode ser vantagem em certas situações na programação. 
O comando goto requer um rótulo para sua operação (um rótulo é um identificador válido em C 
seguido por dois pontos). O rótulo tem de estar na mesma função do goto que o usa – você não 
pode efetuar desvios entre funções. 
A forma geral do goto é: 
 
goto rótulo; 
 . 
 . 
 . 
rótulo: 
 
Onde rótulo é qualquer rótulo válido existente antes ou depois do goto. 
Ex.: 
 
x=1; 
loop1: 
 x++ 
 if(x<100) goto loop1; 
 
 
 
Página 26 de 75 
Contudo, não é comum o uso do comando goto para saltos. È conveniente usar técnicas de 
computação que substituam o comando goto. É recomendável o uso do goto sempre que se pretende 
escrever algo na tela, para o melhor posicionamento de textos na tela do computador. 
Ex: gotoxy (5,5) printf(“Inicio da escrita\n”). 
No exemplo acima se instrui o compilador a se posicionar na posição x=5 e y=5 da tela do monitor e 
nessa posição escrever “Início da escrita”. 
 
4.4.3 — O Comando BREAK 
O comando break tem dois usos. Pode ser usado para terminar um case em um comando switch (já 
apresentado anteriormente). O leitor pode usá-lo, também, para interromper (frear) de modo 
imediato a execução de um laço, evitando o teste condicional normal do laço. Um comando break 
provoca uma saída apenas do laço mais interno, e o controle do programa retorna ao comando 
seguinte ao laço. 
Ex.: 
 #include <stdio.h> 
 void main(void) 
 {int t; 
 for(t=0;t<100;t++) 
 { 
 printf(“%d”, t); 
 if(t==10) break; 
 } 
 } 
 
No exemplo anterior são escritos os números de 1 até 10 na tela. Então, o laço termina porque o 
break provoca uma saída imediata do laço, desrespeitando o teste condicional t<100. 
 
4.4.4 — O Comando CONTINUE 
Este comando é utilizado para forçar que ocorra a próxima iteração do laço, pulando qualquer 
código. Para o laço for, continue faz com que o teste condicional e a porção de incremento do laço 
sejam executados. Para os laços while e do-while, o controle passa para o teste condicional. 
Ex: Neste caso o uso do comando continue é para apressar a saída do laço. 
void main (void) 
{ 
 char alfa, ch; 
 alfa =0; 
 while (!alfa) { 
 ch = getchar( ); 
 if(ch==’$’) 
 { 
 alfa =1; 
 
 
Página 27 de 75 
 continue; 
 } 
 else putchar(ch+1); /* Desloca o alfabeto uma posição */ 
 } 
} 
 
O programa apresentado antes codifica uma mensagem desloca todos os caracteres uma letra acima 
ou na frente. Por exemplo, se for digitado um b se tornaria um c. A função termina quando um $ for 
digitado. 
 
5 — FUNÇÕES 
5.1 - Introdução 
Antes de iniciarmos a abordagem de funções na linguagem de programação C, faremos uma breve 
resenha dos objectivos do uso de funções nas linguagens de programação. 
Em geral se tem problemas complexos, cuja solução requer igualmente algoritmos complexos. No 
entanto, é prática elegante e eficiente em computação dividir algum problema complexo em 
conjuntos de problemas mais simples de se resolver. A isso se chama modularização, ou seja, 
repartição dos problemas grandes e complexos em módulos menores e simples, de tal modo, que a 
aglutinação destas soluções simples resultam na solução do problema complexo. 
O uso de funções aparece na literatura com vários outros nomes, tais como sub-programas, 
procedimentos etc. Independentemente da nomenclatura, toda a função tem um propósito bem 
definido, permite o reaproveitamento do seu código, pode ser executado em diversas situações no 
mesmo programa e/ou em programas diferentes; 
 
As funções são uma das características mais importantes da linguagem de programação C e o local 
onde ocorre toda atividade de um programa. Toda a linguagem de programação C é estrutura em 
termos de funções. Assim, nas próximas secções estudaremos declaração de funções, os argumentos 
das funções e tipos de funções. 
 
5.1.1 — A forma geral de uma função 
Uma função é iniciada pela palavra reservada funcao, seguida de um especificador_de_tipo referente 
ao tipo de retorno da função, do nome da função e de uma lista de parâmetros. 
É da seguinte estrutura: 
 
 especificador_de_tipo nome_da_função(lista de parâmetros) 
 { 
 
 
Página 28 de 75 
 corpo da função 
 } 
 
 
O especificador_de_tipo especifica o tipo de valor que o comando return da função devolve para o 
programa e pode ser de qualquer tipo válido (ex.: int, float, double, string, etc.). Se nada for 
especificado, o compilador assume que a função devolve um resultado inteiro. 
A lista de parâmetros é uma lista de nomes de variáveis seguidas por vírgulas e seus tipos 
associados que recebem os valores dos argumentos quando a função é chamada. A lista de 
parâmetros consiste nos valores que o programa principal possui, e que são necessários a função, 
para obtenção dos dados desejados no programa principal. 
Uma função pode não ter parâmetros, neste caso a lista de parâmetros é vazia, mas mesmo assim os 
parênteses são necessários. Para explicitar claramente, que a função não receberá jamais algum 
parâmetro ela deverá ter na lista de parâmetros a palavra void. 
A declaração das variáveis é similar ao visto no início do curso. Na especificação de 
parâmetros da função devem incluir o tipo e o nome da variável. Na sua forma geral é: 
 
função(tipo nomevar1, tipo nomevar2,...) 
 
Variáveis Locais – só podem ser referenciadas por comandos que estão dentro do 
bloco no qual as variáveis foram declaradas. Uma variável local é criada na entrada de seu bloco 
e destruída na saída. Elas são definidas internamente a uma função. As variáveis locais não podem 
manter seus valores entre chamadas a funções, exceto quando a variável é declarada de tipo de 
cruzamento static, isso faz com que o compilador a trate como uma variável global a fins de 
armazenamento, mas limita o seu escopo para dentro da função. 
 
 
5.1.2 — Argumentos de Funções 
Se uma função usa argumentos, ela deve declarar variáveis que aceitem os valores dos argumentos, 
essas variáveis são chamadas de parâmetros formais da função. Ex: 
 
 
/* Calcula a média de um estudante */ 
 
 float (float nota1, float nota2, float nota3) 
 { float media; 
 media=(nota1+nota2+nota3)/3; 
 return media; 
 } 
 
 
 
 
Página 29 de 75 
Devemos assegurar
sempre que os argumentos usados para chamar a função sejam compatíveis com 
o tipo de seus parâmetros. Se os tipos forem incompatíveis, alguns compiladores geram 
mensagem de erro, em outros ocorrem resultados inesperados. 
 
 
5.1.3 — O comando Return 
 
Provoca uma saída imediata da função que o contém, isto é, faz com que a execução do programa 
retorne ao código chamador. A palavra reservada return identifica qual valor será retornado ao 
programa acionador da função. Se o comando return não fizer parte de uma função, nesse caso as 
funções usam o modo default para terminar a execução, exceto se a função for do tipo void. 
 
 
5.1.4 — Funções que retornam valores inteiros e não-inteiros 
 
Todas as funções, exceto as do tipo void, devolvem um valor, e esse valor é especificado pelo 
comando return. Se nenhum comando return estiver presente, o retorno da função será indefinido. 
Sempre que o tipo da função não é especificado o compilador atribui a ela o tipo padrão int. 
Mas quando é necessário um tipo de dados diferentes o processo dois passos: 
1º) Deve ser dada a função um especificador de tipo explícito; 
2º) O tipo da função deve ser identificado antes da primeira chamada feita a ela. Por isso, usa-se a 
declaração da função antes do programa principal e depois a explicitação do que a função faz após o 
programa principal. Deste modo o C pode gerar um código correto para funções que não devolvem 
valores inteiros. Para evitar que o compilador não devolva um valor inteiro, devemos utilizar uma 
forma especial de declaração, perto do início do programa, informando o compilador que tipo de 
dado sua função realmente devolverá, ou seja, a declaração da função. 
Protótipo de Função: permite os tipos de argumentos das funções sejam declarados, e é um dos 
acréscimos mais importantes do ANSI ao C. A forma geral de uma definição de protótipo de função 
é: 
tipo nome_func(tipo nome_var1,..., tipo nome_varN); 
 
O uso dos nomes dos parâmetros é opcional, mas é bom incluí-los, pois eles habilitam o compilador 
a identificar qualquer incompatibilidade de tipos por meio do nome quando ocorre um erro. 
Sempre existe a questão: “Se deve atribuir esse valor a alguma variável já que um valor está 
sendo devolvido? Não! Se não houver nenhuma atribuição específica o retorno é descartado. 
Ex.: Considere o programa abaixo, que usa as funções soma( ) e divisão(). 
 
#include <stdio.h> 
int soma(int a, int b); /* Protótipo da função soma( ) */ 
 
 
Página 30 de 75 
float divisao( int b, int a) /* Protótipo da função divisao( ) */ 
void main(void) 
 { 
 int a, b, c; 
 a=2; b=3; 
 c=soma(a,b); /* atribui o valor de soma( ) a c */ 
 printf(“%f”, divisao(b,a)); /* o valor de retorno não é atribuído, mas usado por printf */ 
 soma(a,b); /* o valor é perdido porque não é atribuído */ 
 } /* ou utilizado como parte de uma expressão */ 
/* Explicitação da função soma */ 
int soma(int, a, int b) 
 { 
 return(a+b); 
 } 
/* Explicitação da função divisão */ 
float divisao(int, b, int a) 
 { 
 return(b/a); 
 } 
 
 
Todas as funções que não devolvem (retornam) valores devem ser declaradas como retornando o 
tipo void. Ao declarar uma função como void, você a protege de ser usada em uma expressão, 
evitando uma utilização acidental. 
Ex.: 
 
 float calculo(void) 
 
Diz que a função “calculo ” não tem parâmetros, isto é, quando acionado pelo programa principal 
não recebe nada dele, apenas o seu acionamento, mas devolve (retorna) um float. Isso informa ao 
compilador que a função não tem parâmetros e qualquer chamada à função com parâmetros é um 
erro. 
Ex.: Uso de parâmetros de função de modo incompatível originando erro. 
 
/* Este programa usa um protótipo de função para forçar uma verificação de tipos */ 
void quadrado(float *i); /* protótipo */ 
void main(void) 
{ 
 int x; x=10; 
 sqr_it(x); /* incompatibilidade de tipos */ 
} 
void quadrado(int *i) 
 { 
 *i= *i * *i; 
 } 
 
 
 
NOTA: Quando um caractere é devolvido por uma função declarada como o tipo int o valor 
caractere é convertido em um inteiro. Visto que o C faz a conversão de caractere para inteiro, e 
 
 
Página 31 de 75 
vice-versa, uma função que devolve um caractere geralmente é declarada como devolvendo 
caractere, mas pode ser declarada como do tipo int. 
 
5.2 — Passagem de parâmetros (por valor e por referência) 
A criação de funções nem sempre significa que o desenvolvimento do programa principal requererá 
menos esforço do usuário programador. Por exemplo, se o pedissem para elabora um programa que 
calculasse a média da nota de física de 1000 alunos numa prova de vestibular. O que foi apresentado 
até ao momento a lista de parâmetros teria 1000 variáveis notas. O que torna essa enumeração 
exaustiva, assim deve existir uma maneira de reaproveitar a função com ligeiras modificações ou 
adaptações. Por esse motivo, criou-se o conceito de passagem de parâmetros, que representa uma 
maneira de como o programa principal deve fornecer as informações necessárias às funções. A 
passagem de argumentos para funções é feita de duas maneiras: por valor e por referência. 
Chamada ou passagem por valor – o programa principal fornece uma copia do valor de um 
argumento para a função, de modo que alterações feitas nas funções não têm nenhum efeito nas 
variáveis usadas para chamá-las. Com a finalização da execução da função o valor do parâmetro 
passado por valor é destruído. 
 
Chamada ou passagem por referência – o endereço de um argumento é copiado no parâmetro. 
Dentro da função, o endereço é usado para acessar o argumento real utilizado na chamada, significa 
que alterações feitas no parâmetro afetam a variável usada para chamar a rotina. 
Ex. 
 
 
#include<stdio.h> #include<stdio.h> 
 
int sqr(int x); int sqr(int *t) 
void main(void) void main(void) 
{ { 
 int t=5; int t=5; 
 printf(“%d %d”, sqr(t), t); printf(“%d %d”,sqrt(t),t); 
} } 
int sqr(int x) int sqr(int *t) 
 { { 
 x=x*x; *t=(*t)*(*t); 
 return(x); return(*t); 
 } } 
 
 
 
Lembramos, que o argumento para sqr( ), 5 é copiado no parâmetro x. Quando a atribuição x=x*x 
ocorre, apenas a variável local x é modificada. A variável t, usada para chamar sqr( ), ainda tem o 
 
 
Página 32 de 75 
valor 5. Assim, a saída é 25 5. Salienta-se que é uma cópia do valor do argumento que é passada 
para a função. 
No segundo exemplo, o argumento para sqr( ), 5 é passado como parâmetro. Quando a atribuição 
*t=(*t)*(*t), a variável t é modificada. A variável t, usada para chamar sqr( ), não vale mais 5. A 
saída nesse caso é 25 25. 
 
5.3 Funções recursivas (ou de recorrência) 
 
É comum em C, funções chamarem a si mesmas. A função é recursiva se um comando no corpo da 
função a chama. Recursão é o processo de definir algo em termos de si mesmo, e algumas vezes é 
chamado de processo circular.
O uso de uma função recursiva objetiva uma seqüência de chamadas 
até que um certo ponto seja atingido. 
Analisemos a título de exemplo a função recursiva factorial( ) que obviamente calcula o fatorial de 
um número inteiro, isto é, o produto de todos os números inteiros entre n e 1. Tanto factorial( ) 
como sua equivalente iterativas são apresentadas abaixo: 
Ex.: 
 
factorial(int n) /* recursiva */ 
 { 
 int resposta; 
 if (n==1) return(1); 
 resposta=factorial(n-1)*n; /* chamada recursiva */ 
 return(resposta); 
 } 
fact(int n) /* não-recursiva */ 
 { 
 int t, resposta; 
 resposta=1; 
 for(t=1; t<=n; t++) resposta=resposta*(t); 
 return(resposta); 
 } 
 
 
 
A versão não recursiva de fact( ) deve ser clara. Ela usa um laço que é executado de 1 a n e 
multiplica consecutivamente cada número pelo produto móvel. 
A operação da função recursiva factorial( ) é mais complexa. Quando factorial( ) é chamada como 
argumento de 1, a função devolve 1, senão ela devolve o produto de factorial (n-1)*n. Para avaliar 
essa expressão, factorial( ) é chamada com n-1. Acontecerá isso até que n iguale a 1 e as chamadas 
à função comecem a retornar. 
 
 
Página 33 de 75 
Se colocássemos o fatorial de 2, a primeira chamada a factorial( ) provoca uma segunda chamada 
com argumento (n = 2-1 = 1). Essa chamada retorna 1 que é, então, multiplicado por 2 (o valor 
original de n). O resultado, isto é, a resposta é 2. 
Quando uma função chama a si mesma, novos parâmetros e variáveis locais são alocadas na pilha e o 
código da função é executado com essas novas variáveis. Uma chamada recursiva não faz uma 
nova cópia da função, apenas os argumentos são novos. 
A principal vantagem das funções recursivas é que você pode usá-las para criar versões mais claras e 
simples de vários algoritmos. 
 
 
 
5.4 — Classes de armazenamento 
Na linguagem C existem quatro tipos de especificadores de classe de armazenamento, que são auto, 
extern, static e register. Os especificadores atrás mencionados informam ao compilador como a 
variável deve ser armazenada. 
a) Variável auto 
Especificador auto: serve para definir variáveis automáticas que é uma referência para as variáveis 
locais. Na linguagem de programação C as variáveis são, por definição, locais ao bloco em que ela é 
declarada o uso de auto não tem nenhum significado, sendo portanto raramente utilizado. 
 
b) Variável extern 
O especificador de armazenamento precede a declaração da variável: 
 especificador_de_armazenamento tipo nome_da_variável 
O especificador extern diz ao compilador que os tipos e nomes de variável que o seguem foram 
declarados em outro lugar, isto é, elas são variáveis globais sem realmente criar armazenamento para 
elas novamente. As variáveis globais devem ser declaradas em apenas um arquivo (.c, .cpp, .h, .hpp) 
e usadas como extern nos outros. 
Ex. 
 
 float x,y; /* declaração global de x e y */ 
 void main(void) 
 { 
 extern float y; /* uso opcional da declaração extern */ 
 . 
 . 
 . 
 } 
 
 
 
 
Página 34 de 75 
 
Embora as declarações de variáveis extern possam ocorrer dentro do mesmo arquivo da declaração 
global, elas não são necessárias. Sempre que o compilador C encontra uma variável que não foi 
declarada, ele verificar se ela tem o mesmo nome de alguma variável global. Se tiver, o compilador 
assumirá que a variável global está sendo referenciada. 
 
c) Variável static 
Dentro de sua própria função ou arquivo, variáveis static são variáveis permanentes (estáticas), elas 
são reconhecidas fora de sua função ou arquivo (.cpp, .c, .h ou .hpp) , mas mantêm seus valores 
entre chamadas. O especificador static possibilita a definição de variáveis deste tipo na forma: 
 static tipo_da_variável nome_da_variável; 
As variáveis estáticas têm comportamentos diferentes para variáveis locais e globais. 
Variáveis Locais Static – uma variável local que retém o seu valor entre chamadas de função ou 
bloco de código em que elas são declaradas. 
Variáveis Globais Static – aplicar o especificador static a uma variável global informa ao compilador 
para criar uma variável global que é reconhecida apenas no arquivo no qual a mesma foi declarada. 
Embora variável global, rotina(s) em outro(s) arquivo(s) não pode(m) reconhecê-la nem alterar o seu 
conteúdo diretamente. Esse tipo de variáveis são muito usadas em bibliotecas de funções. 
 
Ex. 
 
series(void) /* Series( ) pode produzir um membro da serie, baseado no numero precedente */ 
 { 
 static int serie_num=100; /* serie_num é gerador de série de números */ 
 serie_num=serie_num+23; /* Esse número é atribuído uma só vez,*/ 
 /* na próxima série o valor começa com 123. */ 
 return(serie_num); 
 } 
 
 
 
 
d) Variável register (registrador) 
Esse tipo de variável quando representando variáveis caracteres ou interios são colocados nos 
registradores da CPU (UCP). Já variáveis de tamanho maior como é o caso de matrizes, essas 
não podem ser colocadas em registradores da CPU (UCP). Assim, Como uma variável do tipo 
register pode ser armazenada em um registrador da CPU (UCP), ela não tem endereço, por 
conseqüência nunca deve ser utilizado o operador & para estas variáveis. 
O número de variáveis do tipo register (registrador) num programa é determinado pelo Sistema 
Operacional e específicidade de cada compilador. Existe sempre um limite no uso de varáveis 
 
 
Página 35 de 75 
register, assim que esse limite seja atingido, as restantes variáveis do tipo register são 
transformadas em variáveis comuns de modo automático pelo compilador. 
 
Ex.: 
int main(void){ 
register int i; 
for (i =0; i<1000;i++){ 
 ........} 
} 
 
 
 
6 – Matrizes e strings 
Neste capítulo se aborda as matrizes de dados homogêneas, ou seja, todos os seus elementos são do 
mesmo tipo. Mais adiante, veremos que em C existem as matrizes de dados heterogêneas que 
pressupões a representação de vários tiopos de dados numa única matriz. 
Uma matriz homogênea ou um vetor homogêneo é uma coleção de variáveis do mesmo tipo que é 
referenciada por um nome comum. Um elemento específico da matriz é acessado por intermédio de 
um índice. Cada posição de armazenamento é chamada de elemento da matriz (ou do vetor). 
 O endereço de índice mais baixo corresponde ao primeiro elemento e o mais alto o último elemento. 
As matrizes podem ter uma a várias dimensões. A matriz mais comum em C é a de string, que é uma 
matriz de caracteres terminada por um nulo. 
 
6.1 — Matrizes Unidimensionais 
As expressões matriz e vetor são sinônimos para alguns casos, mas é bom deixar claro que elas são 
diferentes em termos conceituais. Assim, por vetor sempre se referencia uma matriz unidimensional, 
enquanto que matriz referencia sempre a matriz com uma ou mais dimensões, sendo identificada 
como matriz multidimensional. 
A forma geral para declarar uma matriz unidimensional é: 
 tipo nome_var [dimensão] 
tipo  declara o tipo de base da matriz, que é o tipo de cada elemento da matriz 
dimensão  define quantos elementos a matriz irá guardar. 
Ex.: Para declarar uma matriz de 20 elementos, de nome calculo e do tipo float, declare como: 
 
 
Página 36 de 75 
 
float calculo [20]; 
 
Em C, toda matriz tem 0 (zero) como índice do seu primeiro elemento. Logo quando escrevemos: 
 
 char a[20]; 
Matrizes unidimensionais são, essencialmente, listas
de informações do mesmo tipo, que são 
armazenadas em posições contíguas de memória em uma ordem de índice. 
O esquema abaixo mostra como uma matriz “ch” apareceria na memória se ela começasse na 
posição 40 da memória e fosse declarada como mostramos abaixo: 
char ch[5]; 
Elemento ch[0] ch[1] ch[2] ch[3] ch[4] 
Endereço 40 41 42 43 44 
No acesso a cada elemento de uma matriz deve-se percorrer todo matriz, ou seja, todos os seus 
elementos. Particular atenção deve ser prestada a primeira posição de um elemento é a posição zero 
(0), ou seja, uma matriz é iniciada no elemento zero. Que difere da álgebra linear em que o primeiro 
elemento da matriz encontra-se na posição um (1). 
 
Estamos declarando uma matriz de caracteres com 20 elementos, a[0] até a[19]. Por exemplo, o 
seguinte programa carrega uma matriz inteira com números de 0 a 49. 
 
#include<stdio.h> 
void main(void) 
{ 
 int z[50]; /* Isto reserva 50 elementos inteiros */ 
 int x; 
 for(x=0; x<50;x++) { 
 z[x]=x; 
 printf(“z[%d]=%d\n”, x, z[x]); 
 } 
} 
 
 
C não tem verificação de limites em matrizes. Você poderia ultrapassar o fim de uma matriz e 
escrever os dados de alguma outra variável ou mesmo no código do programa. Cabe ao 
programador, verificar os limites até onde necessário. A título de exemplo temos o programa abaixo, 
onde o código compila sem erros, mas é incorreto, porque o laço for fará com que a matriz 
modulo, ultrapasse seus limites, e escreverá para dos dados sobre outros espaços de memória já 
alocados a outras variáveis. 
 
 
 
Página 37 de 75 
int modulo{20], y; 
/* Isto faz com que modulo seja ultrapassada */ 
for (x=0;y<=100;y++) modulo[y]=y; 
6.2 — Matrizes com Duas ou Mais Dimensões 
C suporta matrizes multidimensionais. A forma mais simples de uma matriz multidimensional é a 
matriz bidimensional – uma matriz de matrizes unidimensionais, ou seja, uma matriz composta por 
linhas e colunas. Para declarar uma matriz bidimensional de inteiros d composta por 5 linhas e 8 
colunas , escrevemos: 
 
 int d[5][8]; 
 
Em C cada dimensão da matriz é colocada no seu próprio colchete, em contraste com outras 
linguagens que usam a vírgula para separar as dimensões: [1,5]. 
Matrizes bidimensionais são armazenadas em uma matriz linha-coluna, onde o primeiro índice 
indica a linha e o segundo a coluna. Isso significa que o índice mais a direita varia mais 
rapidamente do que o mais à esquerda quando acessamos os elementos da matriz na ordem em que 
eles estão realmente armazenados na memória. 
 
Ex.: d[3][3] 
 
Direito determina a coluna 
 
d[0][0] d[0][1] d[0][2] 
 
d[1][0] d[1][1] d[1][2] 
 
Esquerdo 
determina a linha 
 
d[2][0] d[2][1] d[2][2] 
 
Figura 6.1 – Uma matriz bidimensional na memória. 
 
 
Ex.: O seguinte programa carrega uma matriz bidimensional com números de 1 a 9, e escreve-os 
linha por linha. 
 
#include<stdio.h> 
void main(void) 
{ 
 int x, y, a[3][3]; 
 
 
Página 38 de 75 
 for(x=o;x<3;x++) 
 { 
 for(y=0;y<3;y++) 
 a[x][y]=(x*3)+y+1; 
 } 
/* Escrita dos números */ 
 for(x=o;x<3;x++) { 
 for(y=0;y<3;y++) 
 printf(“%d”, a[x][y]); 
 printf(“\n”) 
 } 
} 
 
 
A forma geral da declaração de uma matriz multidimensional é: 
 
tipo nome_var [tamanho1][tamanho2]...[tamanhoN]; 
 
Ex.: 
 
int m[4][3][5]; /* declaração de uma matriaz multidimensioanal*/ 
 
 int resultado = m[2][1][4] ; /* valor da posição daa matriaz */ 
 
Matrizes de três ou mais dimensões não são freqüentemente usadas devido a quantidade de 
memória que elas necessitam. As grandes matrizes multidimensionais são geralmente alocadas 
dinamicamente, através das funções de alocação dinâmica de C e ponteiros. Essa abordagem é 
discutida nas chamadas matrizes esparsas, que está fora do escopo desta apostila. 
Ex: Inicialização de uma matriz multidimensional 
int matriz[3][4][2] = {{{1,5},{2,6},{3,7},{4,8}},{{3,7},{4,9}, 
 {5,4},{6,5}},{{1,0},{4,6},{6,7},{7,8}}}; 
 
 1,2,3,4 5,6,7,8 
 3,4,5,6 7,9,4,5 
 1,4,6,7 0,6,7,8 
 
 Pagina 1 Pagina 2 
 
6.3 — Matrizes como Argumentos de Funções 
Em C, não se pode passar uma matriz inteira como um argumento para uma função. 
 
 
Página 39 de 75 
Para as matrizes unidimensionais, somente o nome da matriz, desacompanhado dos colchetes, 
equivale ao endereço da matriz. O endereço da matriz é igual ao endereço do primeiro elemento 
(posição[0]), enquanto que o endereço dos outros elementos são diferentes. 
Se uma função recebe uma matriz unidimensional, podemos declarar o parâmetro formal em uma das 
três formas: 
a) Passar um ponteiro para uma matriz para uma função, especificando o nome da matriz sem 
índice 
 void teste(int *y) /* Ponteiro*/ 
 { 
... 
} 
 
b)Passar um ponteiro para uma matriz para uma função, especificando o nome da matriz sem um 
índice: 
 
Ex.: 
 void teste (int y[20]) /* Matriz dimensionada */ 
 { 
 . 
 . Porque o compilador gera um código que instrui teste( ) a 
 . receber um ponteiro – ele não cria uma matriz de 20 
 } elementos. 
 
c) Como uma matriz não-dimensionada – declara que uma matriz do tipo declarada, de algum 
tamanho, será recebida. 
 O comprimento da matriz não importa porque o C não verifica os limites. 
Ex.: 
 void teste(int y[ ]) /* Matriz dimensionada */ 
{ 
 . 
 . 
 . 
} /* Uma matriz sem um índice, é um ponteiro para o 1º elemento da matriz */ 
 
 
Página 40 de 75 
Obs.: Todos os três métodos de declaração produzem resultados idênticos, pois cada um diz ao 
compilador que é um ponteiro para inteiro vai ser recebido. 
Quando uma matriz bidimensional é usada como argumento para uma função, apenas um ponteiro 
para o primeiro elemento é realmente passado. Porém, uma função que recebe uma matriz 
bidimensional como um parâmetro deve pelo menos definir o comprimento da segunda dimensão. 
Isso ocorre porque o compilador C necessita saber o comprimento de cada linha para indexar a 
matriz corretamente. 
Ex.: 
 
int y[5][5]; 
 
 Pode ser declarada como: 
void func1(int y[ ][5] 
{ 
 . 
 . 
 .} 
 
 
6.4 — Strings e Funções de Manipulação 
O uso mais comum de matrizes unidimensionais é como string de caracteres. Em C, uma string é 
definida como uma matriz de caracteres que é terminada por um nulo (‘\o’). Por esse motivo, 
declaram-se sempre matrizes de caracteres como sendo um caractere mais longo que a maior string 
que elas devem guardar. 
Uma cadeia de caracteres (ou string de caracteres) consiste em uma matriz homogênea do tipo 
escalar char (caracter) que ocupa 1 byte (8 bits) de memória para cada caracter, e a sua declaração é 
da forma: 
 char nome_da_variável [tamanho]; 
 
a) Leitura de strings 
A leitura de strings de caracteres pode ser feita com a função scanf(), ela sempre acrescenta o 
‘\0’ no primeiro espaço em branco que encontrar na cadeia de caracteres, desprezando o restante 
da string. Por outro lado, não é necessário o uso do operador &, pois o nome da string é o seu 
endereço inicial. 
 Ex: scanf(“%s”, cidade); 
 
 
Página 41 de 75 
Outra maneira de fazer a

Teste o Premium para desbloquear

Aproveite todos os benefícios por 3 dias sem pagar! 😉
Já tem cadastro?

Continue navegando