Escolar Documentos
Profissional Documentos
Cultura Documentos
Fev/2008
Rômulo C. Silva
Conteúdo do Curso
Linguagem C:
Histórico
Sintaxe básica: Identificadores e Controle de fluxo
Tipos básicos
Operadores
Vetores e Matrizes
Strings
Ponteiros
Funções
Arquivo de header
Argumentos via linha de comando
Manipulação de arquivos
Estrutura e uniões
Ponteiros para funções
Rômulo C. Silva
Introdução
Rômulo C. Silva
Linguagem C – Histórico
Criada nos laboratórios da companhia Bell Labs por Brian
Kernighan e Dennis Ritchie em 1972
Características principais:
Adequada à programação estruturada
Oferece bom nível de portabilidade
Acessos a recursos de baixo nível
Geração de código eficiente
Rômulo C. Silva
Linguagem C
Fases para construção de um programa C:
Escrita do código fonte em algum editor de texto
Passar o pré-processador
• Gera código-fonte expandido
Compilar o código
• Gera código-objeto
Rômulo C. Silva
Sintaxe
A sintaxe de uma linguagem é composta de
regras que definem as construções válidas
na linguagem.
Regras para formação de identificadores
Palavras-reservadas
Regras para definição de escopo de variáveis
Ordem de execução de instruções
Precedência de operadores
Rômulo C. Silva
Linguagem C - sintaxe
Regras básicas:
As instruções são finalizadas com ponto-e-
vírgula (;)
Comentários entre /* e */
identificadores de variáveis ou funções:
• devem iniciar com letra ou underscore (_)
• Os 32 primeiros caracteres de um identificador são
significativos
Case sensitive: letras maiúsculas são
consideradas diferentes de minúsculas
• Ex.: valor ≠ VALOR ≠ Valor ≠ vAlor
Rômulo C. Silva
Linguagem C - Tipos
O tipo de um identificador visa definir os
valores possíveis de serem atribuídos ou
associados a ele, além das operações
válidas
Análogo ao conceito de domínio em Matemática
Rômulo C. Silva
Linguagem C - Tipos
Tipos de Funções
Tipos de dados:
Escalares
• Tipos aritméticos
– Caracter, inteiros e ponto flutuante
• Tipos ponteiros
Não-escalares
• Estrutura
• União (union)
• Vetores e matrizes
Rômulo C. Silva
Linguagem C – Tipos Básicos
char
representa um caracter, armazenado em código ASCII
int
inteiro padrão, faixa de valores depende da plataforma
float
número em ponto flutuante de precisão simples.
double
número em ponto flutuante de precisão dupla.
void
indica um tipo indefinido. Uma das aplicações deste tipo
em C é designar um tipo vazio, que posteriormente pode
ser convertido para algum dos tipos anteriores.
Rômulo C. Silva
Linguagem C – modificadores de
tipos básicos
Usados para alterar a faixa de valores que
um tipo pode assumir
signed
Indica números representados com sinal
(positivos ou negativos)
unsigned
Apenas números positivos
long
Em geral, aumenta o número de bits
short
Em geral, diminui o número de bits
Rômulo C. Silva
C ANSI – tipos básicos
Tipo Tamanho em Faixa de Valores
Bytes
char 1 -127 a 127
int 4 -2.147.483.648 a
2.147.483.647
unsigned int 4 0 a 4.294.967.295
Rômulo C. Silva
C ANSI – Tipos básicos
unsigned short 2 0 a 65.535
int
signed short int 2 -32.768 a 32.767
Rômulo C. Silva
Linguagem C - constantes
Inteiras: valores numéricos sem ponto decimal.
Exs.:
2008
+5
-3
0
Inteiras longas: acrescenta-se um L (maiúsculo)
no fim.
25000L
+37L
-50000L
Obs.: Em geral, nas máquinas atuais, int e long
int tem o mesmo número de bytes
Rômulo C. Silva
Linguagem C - constantes
Octais: números representados na base 8 (octal).
São indicados com a inclusão de um 0 (zero) no
início.
025 (21 na base decimal)
077 (63 na base decimal)
0175 (125 na base decimal)
Rômulo C. Silva
Linguagem C - constantes
Ponto Flutuante: representam números
reais, considerados do tipo “double”.
Representadas usando ponto decimal,
podendo ser expressas usando notação
científica. Exs:
-173.49
738.32e-10
Rômulo C. Silva
Linguagem C – constantes
caracteres
representa um único caracter. Indicado
entre ‘ e ‘ (apóstrofo). Exs.:
‘a’ (corresponde ao caracter a)
‘A’ (corresponde ao caracter A)
Rômulo C. Silva
Linguagem – constantes
caracteres
Caracteres especiais (não visíveis) são
identificados através de \ (barra invertida).
Exs.:
‘\t’ (tabulação horizontal)
‘\r’ (carriage return)
‘\n’ (nova linha)
‘\0’ (Null, indica fim de string em C)
Rômulo C. Silva
Linguagem C – constantes
cadeias de caracteres
Indicadas entre “ e “ (aspas)
“isto eh uma cadeia de caracteres em C”
“hello world!”
Automaticamente o C inclui um ‘\0’ (fim de
string).
Usa-se \“ para o caracter “ (aspas) e \\
para o caracter \ (barra) dentro uma
cadeia. Exs.:
“aqui vem uma \” no meio da cadeia”
“coloque uma \\ na cadeia”
Rômulo C. Silva
Linguagem C – palavras
reservadas
Servem para definir significado
computacional específico dentro da
linguagem
Guiam o processo de
compilação/interpretação do código-fonte.
Rômulo C. Silva
Linguagem C – exemplo de
programa
main() {
Programa principal
int x, y;
int z = 2;
y = 5;
Declaração e inicialização
x = y; de variável
z = x + y;
printf(“soma: %d“, z);
return 0;
}
Impressão de mensagem na console
Rômulo C. Silva
Linguagem C – declaração de
variáveis
Tipo da variável seguido do(s) identificador(es),
podendo ser inicializada ou não.
float x;
char ch = ‘A’
int y=5;
double r,s,t;
Rômulo C. Silva
Conversão entre tipos
Na avaliação de expressões contendo tipos
diferentes, o compilador verifica se é possível
converter um tipo em outro segundo as regras:
Todos char e short int são convertidos para int
Todos os float são convertidos para double
Para pares de operandos:
• Se um é long double, o outro é convertido para long double
• Se um é double, o outro é convertido para double
• Se um é long, o outro é convertido para long
• Se um é unsigned, o outro é convertido para unsigned
Rômulo C. Silva
Modelador (Cast)
Força uma expressão ser de um tipo
especificado.
Sintaxe:
(tipo) expr;
tipo é o tipo para o qual expr deve ser
convertida.
Ex.:
int a = 7;
int b = 13
float x = (float) (a+b)/3;
Rômulo C. Silva
Linguagem C – entrada e saída
básicas
função printf
Definida pela biblioteca stdio.h
Imprime uma mensagem na console (saída)
Formato:
• printf(“expr. de controle”, arg1, arg2, arg3, …)
A expressão de controle consiste de uma
mensagem com indicação de formatação
• %c : um único caracter
• %d : decimal
• %e : número em notação científica
• %f : ponto flutuante
• %s : cadeia de caracteres
Rômulo C. Silva
Linguagem C – entrada e saída
básicas
Rômulo C. Silva
Linguagem C – entrada e saída
básicas
função scanf:
Lê do teclado e armazena o valor em variáveis
Formato:
• scanf(“expr. de controle”, arg1, arg2, arg3, …)
Expressão de controle usa os mesmos códigos
de formatação de printf.
Número de argumentos também é variável
Os argumentos devem ser o endereço de
memória onde os valores serão armazenados
• Indicado pelo operador &
Rômulo C. Silva
Linguagem C – entrada e saídas
básicas
main() {
int x, y;
char ch;
printf(“entre com dois inteiros:\n”);
scanf(“%d%d”, &x, &y);
printf(“digite um caracter: \n”);
scanf(“%c”, &ch);
return 0;
}
Endereço de memória
da variável ch
Rômulo C. Silva
Linguagem C - operadores
Aritméticos:
+ (adição), - (sutração), * (multiplicação),
/ (divisão), % (módulo – resto da divisão inteira)
Atribuição:
=
Relacionais
>, <, <=, >=, ==, !=
Lógicos
&& (and), || (or), ! (not)
Manipulação de bits
& (and), | (or), ^ (xor), << (shift à esquerda),
>> (shift à direita), ~ (not)
Rômulo C. Silva
Linguagem C - operadores
Atribuição
Precedência à direita.
int x = y = z = 3;
• O valor 3 é atribuído a z , depois o valor de z é atribuído a y e por
último o valor de y é atribuído a x.
Relacionais
Resultado é 0 (falso) ou 1 (verdadeiro)
7>3
• Resulta em 1 (verdadeiro)
3 == 2
• Resulta em 0 (falso)
Rômulo C. Silva
Linguagem C
Não existem variáveis booleanas em C, qualquer
valor pode ser testado como verdadeiro ou falso
Rômulo C. Silva
Linguagem C – operadores bit a
bit
Só podem ser usados com números inteiros
Rômulo C. Silva
Linguagem C – atribuições
reduzidas
Forma: x op= y
Equivale a:
• x = x op y
Onde op pode ser: +, -, / , *, %, << , >>, |, &,
^
Exemplos:
a += 2 significa a = a + 2
x /= z significa x = x/z
r += (y + 8) significa r = r + (y+8)
Rômulo C. Silva
Linguagem C – operadores pré e
pós-fixados
Usados para incrementar ou decrementar variáveis
Pré-fixados:
Antecedem o nome da variável
Ex.:
int i = 2;
++i; /* i vale 3 após essa linha */
Pós-fixados:
Seguem o nome da variável
Ex.:
int j = 5;
j--; /* j vale 4 após essa linha */
Rômulo C. Silva
Operadores pré e pós-fixados
Operadores pré-fixados e pós-fixados são
esquivalentes se usados isoladamente
Em expressões aritméticas:
Pré-fixado: o incremento (ou decremento) é executado
primeiro, e depois o valor é usado.
Ex.:
int i=7;
int x = ++i; /* x e i valem 8 após essa linha */
Pós-fixado: primeiro o valor é usado, e depois é realizado
o incremento (ou decremento).
Ex.:
int i=5;
int y=i--; /* y vale 5 e i vale 4 após essa linha */
Rômulo C. Silva
Controle de Fluxo – comando if
Sintaxe:
if(expr)
cmd ou
if(expr)
cmd1
else
cmd2
expr é uma expressão cujo valor pode ser zero
(falsa) ou diferente de zero (verdadeira)
cmd, cmd1 e cmd2 são comandos finalizados por ;
ou bloco de comandos delimitados por {}
Rômulo C. Silva
Comando if - exemplo
int x = 5;
int y = 7;
if(x == 3) /* será avaliado como falso */
printf(“x vale 3”);
Rômulo C. Silva
Comando if – cuidado!!!
Operador de atribuição
int x = 5;
if(x = 3) /* será avaliado como verdadeiro!!! */
printf(“x vale 3”);
Rômulo C. Silva
Controle de Fluxo - while
Sintaxe:
while(expr)
cmd
cmd é um comando finalizado por ; ou um bloco
de comandos delimitados por {}
enquanto expr for verdadeira (diferente de
zero), o comando é executado.
Rômulo C. Silva
Comando while - exemplo
int i = 1;
while (i < 10) {
printf(“valor de i: %d”, i);
i++;
}
Rômulo C. Silva
Controle de Fluxo – comando
do-while
Sintaxe:
do
cmd
while(expr)
Rômulo C. Silva
Comando do-while - exemplo
int i = 1;
do {
printf(“%d \n”, i);
i++;
}
while(i < 10)
Rômulo C. Silva
Controle de Fluxo – comando for
Sintaxe:
for(inicializacao; condicao; incremento)
cmd
Equivalente ao comando while
Ex.:
int i;
for(i = 1; i < 10; i++)
printf(“%d\n”, i);
Rômulo C. Silva
Comando for
Tanto a expressão de inicialização, condição
e incremento podem conter várias
instruções separadas por vírgula
Ex.:
inicialização incremento
int i, j;
for(i = 0, j = 3; i + j < 25; i++, j++) {
printf(“i vale: %d\n”, i);
printf(“i+j vale: %d\n”, i+j);
}
Rômulo C. Silva
Comando for
Qualquer uma das três partes (inicialização, teste
ou incremento) pode ser omitida
Se a expressão de teste é omitida, então é sempre
avaliada para verdadeira.
Além disso, a parte de comandos também pode ser
omitida.
Ex.:
sem inicialização
int i = 4;
for( ;i < 9; i++)
printf(“i vale: %d\n”, i);
Rômulo C. Silva
Comando for - exemplo
int i = 1;
/* exemplo de for sem corpo */
for( ; i < 10; i++, printf(“valor de i: %d\n”, i));
incremento
Rômulo C. Silva
Controle de Fluxo – comando
break
Pode ser usado dentro de qualquer estrutura de
laço (for, while, do-while)
Causa a saída imediata do laço
Ex.:
int i = 5;
while(1) { /* sempre verdadeiro */
if(i == 9)
break; /* sai quando i valer 9 */
i++;
}
printf(“saiu do laço“);
Rômulo C. Silva
Controle de Fluxo – comando
switch
Sintaxe:
switch(expr) {
case constante1:
cmd1;
case constante2:
cmd2;
case constante3:
cmd3;
...
default:
cmdN;
}
cmd1, cmd2, ..., cmdN são opcionais
default também é opcional
Rômulo C. Silva
Controle de Fluxo – comando
switch
Procura por uma constante cujo valor seja
o mesmo de expr. Se encontrar, executa o
comando correspondente
Rômulo C. Silva
Comando switch - exemplo
int x;
...
será executado para
switch(x) { x igual a 1, 2 ou 3
case 1:
case 2:
case 3:
printf(“Escolheu 1, 2 ou 3”); break;
case 4:
printf(“escolheu 4”); break;
}
Rômulo C. Silva
Operador ?
O operador ? pode ser usado decidir o
retorno mediante a avaliação de uma
expressão
Sintaxe:
condicao ? expr1 : expr2
Semelhante a um comando if
Se condicao é avaliada como verdadeira
(diferente de zero) então expr1 é retornada,
senão retorna-se expr2
Rômulo C. Silva
Operador ? - exemplo
int a, b, c;
... /* b e c assumem valores neste trecho de
código */
a = (b > 7)? (b+5) : c
equivale a:
int a, b, c;
... /* b e c assumem valores neste trecho de
código */
if(b > 7)
a = b+5;
else
a = c;
Rômulo C. Silva
Introdução a funções
Função em C: bloco de código que pode ser usado
diversas vezes
A função main indica o ponto de início da execução
do programa -> programa principal
Um programa em C consiste de um conjunto de
várias funções colocadas juntas
Podem ter argumentos ou não
Devem indicar o tipo de retorno
Declara-se do tipo void quando não é necessário retornar
valor
Pontos de retorno são indicados pelo comando
return
Rômulo C. Silva
Introdução a funções
Sintaxe:
tipo_de_retorno nome_funcao(parametros) {
comandos
}
Nome da função segue as mesmas regras de
formação de identificadores de variáveis
Em geral costuma-se nomear as funções em
letras minúsculas
Rômulo C. Silva
Funções - exemplo
int soma(int x, int y) {
return x+y;
Parâmetros formais
}
tipo da função
void imprime(int x) {
printf(“valor: %d”,x);
}
invocação da
main() { função soma
int r = soma(7,5);
imprime(r);
}
Rômulo C. Silva
Linguagem C – Strings (básico)
Em C, uma string é um vetor de caracteres
terminado pelo caracter nulo (representado por
‘\0’)
Sintaxe de declaração:
char ident_string[tamanho];
tamanho é o número máximo de caracteres que poderá
ser atribuído a ident_string, incluindo o caracter nulo.
Posições não usadas ficam com valores indeterminados
(“lixo”).
Ex.:
char nome[10]; /* cabem 9 caracteres e mais
o caracter nulo */
Rômulo C. Silva
Linguagem C – Strings (básico)
Pode-se usar a função gets para ler uma
string do teclado
O caracter nulo é adicionado automaticamente
ao pressionar a tecla enter.
A função puts imprime uma string na tela
Ex.:
char str[50];
printf(“digite uma string: “);
gets(str);
printf(“\n voce digitou: ”;
puts(str);
Rômulo C. Silva
Linguagem C – Strings (básico)
Rômulo C. Silva
Linguagem C - Strings
A biblioteca string.h contém funções utilitárias
para manipulação de strings
Rômulo C. Silva
Linguagem C – cópia de Strings -
exemplo
char str1[20];
char str2[10] = “numero”;
char str3[10] = “cadeia3”;
strcpy(str1, str2); // ok! copia str2 em str1
str2 = str3; // NÃO faça isto!!! ERRADO!!!
int i;
for(i = 0; str[3]; i++)
str2[i] = str3[i]; //ok! copia caracter a caracter
str2[i] = ‘\0’; // coloca fim de string
Rômulo C. Silva
Linguagem C - Strings
Concatenação de strings: função strcat
Comparação de strings: função strcmp
Retorna 0 (zero) se são idênticas
Rômulo C. Silva
Linguagem C - Strings
Comprimento da string: função strlen
O terminador nulo NÃO é contado
Rômulo C. Silva
Linguagem C – Vetores e
Matrizes
Vetor: uma matriz unidimensional
Sintaxe:
tipo nomeVetor[tamanho];
Ex.:
int vet[30]; /* o compilador irá alocar 30
posições do tamanho de um int (4 bytes)
dando um total de 120 bytes. */
Rômulo C. Silva
Linguagem C – Vetores e
Matrizes
Índice sempre começa da posição 0 (zero)
Importante: o C não checa os limites do
vetor!!!
Acesso a uma posição fora
do limite declarado
int vet[20];
vet[35] = 2; /* compilador não acusa
erro!!! Porem, isto pode causar erro
durante a execucao!!! */
Rômulo C. Silva
Linguagem C - Matrizes
Sintaxe:
tipo nomeMatriz[NumLinhas][NumColunas];
Ex.:
int matriz[10][20]; /* 10 linhas e 20 colunas */
matriz[0][0] = 57; /* acessa o elemento na linha
zero e coluna zero */
matriz[3][2] = 91; /* acessa o elemento na linha
3 e coluna 2 */
Rômulo C. Silva
Linguagem C - Matrizes
Podem ser de várias dimensões.
Sintaxe:
tipo nomeMatriz[tam1][tam2]...[tamN];
Rômulo C. Silva
Linguagem C - Matrizes
A inicialização pode ser feita um elemento
por vez ou toda a matriz de uma única vez.
Exs.:
Rômulo C. Silva
Linguagem C - Matrizes
O C permite declarar matrizes sem
inicializar uma das dimensões
Após a variável ser inicializada, sua dimensão
não poderá mais ser alterada.
Ex.:
char textoLongo[] = “escrever um texto grande,
dificil de contar os caracteres”;
Rômulo C. Silva
Linguagem C - Ponteiros
São variáveis que guardam endereços de
memória, endereços esses que armazenam
algum tipo específico de dado.
Sintaxe de declaração:
tipo *nomePonteiro;
Ex.: Ponteiro para int
int* ptrInt;
char* ptr2;
Ponteiro para char
Rômulo C. Silva
Linguagem C - Ponteiros
O asterisco (*) é que indica que a variável
é do tipo ponteiro.
CUIDADO!!!: apesar do símbolo ser o mesmo do
sinal de multiplicação, neste contexto ele tem
outro significado.
Podem ser declarados na mesma linha de
variáveis normais.
Ponteiros não inicializados apontam para
posições de memória indefinida (isto é, o
conteúdo é “lixo”);
Ex.:
int x, y, *ptr1, *ptr2;
Rômulo C. Silva
Linguagem C - Ponteiro
Pode ser inicializado para guardar endereço
de outras variáveis já conhecidas através
do operador &
Rômulo C. Silva
Linguagem C - Ponteiros
int x = 5;
int *ptr;
ptr = &x; /* ptr guarda o endereço de
memória da variável x */
Memória
x
5
ptr
Obs.: *ptr pode ser usado
em qualquer lugar que x
seria usado
Rômulo C. Silva
Linguagem C - Ponteiros
int x = 5;
int *ptr;
ptr = &x;
*ptr = 7; /* apos essa linha x vale 7 */
Memória
x
7
ptr
Rômulo C. Silva
Linguagem C – Ponteiros -
exemplo
int x = 7;
int y = 9;
Memória
int *ptrx, *ptry;
x
ptrx = &x; 7
ptry = &y; ptrx
ptry
y
9
Rômulo C. Silva
Linguagem C – Ponteiros -
exemplo
int x = 7;
int y = 9;
Memória
int *ptrx, *ptry;
x
ptrx = &x; 9
ptry = &y; ptrx
*ptrx = *ptry;
ptry
y
9
A posição de memória
apontada por ptrx recebe
o valor armezando na posição
de memória apontada por ptry
Rômulo C. Silva
Linguagem C – Ponteiros -
exemplo
int x = 7;
int y = 9;
Memória
int *ptrx, *ptry;
x
ptrx = &x; 7
ptry = &y; ptrx
ptrx = ptry;
ptry
y
9
Rômulo C. Silva
Linguagem C – Aritmética de
Ponteiros
Ponteiros podem ser somados ou subtraídos, que
corresponde a avançar ou voltar posições de
memória
Dado um ponteiro ptr para um tipo qualquer:
ptr++ avança uma posição de N bytes, onde N é o
tamanho em bytes do tipo para o qual ptr aponta.
ptr-- retrocede uma posição de N bytes, onde N é o
tamanho em bytes do tipo para o qual ptr aponta.
Ex.:
int *ptrx;
double *ptry;
...
ptrx++; /* avança 4 bytes (tamanho do tipo int) */
ptry--; /* retrocede 8 bytes (tamanho do tipo double) */
Rômulo C. Silva
Linguagem C – Aritmética de
Ponteiros
Só é permitido somar e subtrair valores
inteiros
Rômulo C. Silva
Linguagem C - Ponteiros
O conteúdo de ptr
int x = 7; é incrementado. Logo
int *ptr; x passa a valer 8
ptr = &x;
(*ptr)++;
int y = *(ptr++);
Rômulo C. Silva
Linguagem C - Ponteiros
...
int *ptrx; Compara endereços
int *ptry; de memória
...
if(ptrx == ptry)
printf(“apontam para o mesmo endereco”);
Compara conteúdos
if(*ptrx == *ptry) dos endereços
printf(“conteudos iguais”); de memória
Rômulo C. Silva
Linguagem C - Ponteiros
Ponteiro para ponteiro: indireção múltipla
Sintaxe:
tipo **nomePonteiro;
Memória
Guarda o endereço de uma
x
variável do tipo ponteiro. ptrPtrInt 5
Ex.:
int x = 5;
ptrInt
int *ptrInt = &x;
int **ptrPtrInt = &ptrInt;
Rômulo C. Silva
Linguagem C - Ponteiros
Problemas com ponteiros:
Atribuição de valores ao conteúdo de ponteiros
não inicializados tem resultados imprevisíveis.
Ex.:
int x = 5;
int *p;
*p = x; /* p aponta para onde??? */
Rômulo C. Silva
Linguagem C – Ponteiros e
Matrizes
Um vetor em C equivale a um ponteiro
Um ponteiro em C equivale a um vetor
int vet[10];
px guarda o endereço
int *px, *py, *pz; de vet[0]
int elem;
... py também guarda o
px = vet; endereço de vet[0]
Rômulo C. Silva
Linguagem C – Matrizes e
Ponteiros
Matrizes e ponteiros podem ser combinados
de várias maneiras:
z = *v[3];
Rômulo C. Silva
Funções – Passagem de
parâmetros
Em C há somente passagem de parâmetros
por valor:
Valores são copiados para os parâmetros
formais declarados na função
Rômulo C. Silva
Funções – passagem de
parâmetros - exemplo
int soma(int x, int y) {
parâmetros do tipo
return x + y;
ponteiro
}
Rômulo C. Silva
Funções –passagem de
parâmetros
Funções sem declaração de tipo de retorno são
consideradas int por default.
A declaração explícita de uma função sem
parâmetros é feita colocando-se void no lugar dos
parâmetros.
Ex.: função sem parâmetro
float getValorPI(void) {
return 3.14;
}
soma(int x, int y) { função sem indicação
de tipo de retorno
return x + y;
}
Rômulo C. Silva
Função main
pode ser declarada com 2 parâmetros para
capturar argumentos passados via linha de
comando
int main(int argc, char * argv[])
argc indica o número de argumentos passados
argv é um vetor de strings, onde cada string
corresponde a um parâmetro
argv[0] contém o nome do próprio executável
argv[1] contém o primeiro argumento, argv[2]
o segundo, argv[3] o terceiro, e assim por
diante
Rômulo C. Silva
Função main
/* arquivo prog.c
executavel: prog.exe */
int main(int argc, char* argv[]) {
printf(“nome deste programa: %s\n”, argv[0]);
for(int i = 1; i < argc; i++)
printf(“argumento = %s\n“, argv[i]);
}
void
• Não retorna nenhum valor
• Obs.: Não aceito por alguns compiladores!!
Rômulo C. Silva
Funções – quantidade variável de
parâmetros
O programador pode definir funções com
quantidade indefinida de parâmetros
indicado por “...” no lugar dos parâmetros
não conhecidos
A função deve ter pelo menos um
parâmetro formal
Semelhante ao que ocorre com as funções
pré-definidas printf e scanf
A biblioteca stdarg.h contém macros pré-
definidos que permitem a manipulação dos
argumentos não especificados.
Rômulo C. Silva
Funções – quantidade variável de
parâmetros - exemplo
int funcaoArgVar(char* msg1, char* msg2, ...) {
int res = 0;
va_list ap; /* tipo definido em stdarg.h */
va_start(ap,msg2); /* informa o último parâmetro formal */
printf("%s\n", msg1);
for(;;) { /* loop infinito até encontrar o valor zero */
int x = va_arg(ap,int); /* obtém argumento */
if(x == 0)
break;
res += x;
} Argumentos variáveis
va_end(ap);
printf("%s\n", msg2);
return res;
}
void main() {
int r = funcaoArgVar(“Arg Var”,“pronto!”,7,3,11,2,8,9,0 );
printf(“soma = %d”, resultado);
}
Rômulo C. Silva
Protótipos de funções
Funções devem estar definidas antes de serem
usadas
Ex.:
int soma(int x, int y) {
return x+y;
}
int main() {
int x = soma(4,5); /* essa está OK! */
int y = mult(4,5); /* erro!!! */
}
int mult(int x, int y) {
return x*y;
}
Rômulo C. Silva
Protótipos de funções
Uma forma de usar funções antes da
definição de seu código é através da
declaração de seu protótipo
Sintaxe:
tipo nomeFuncao(parametros);
Rômulo C. Silva
Protótipos de Funções - exemplo
int mult(int x, int y);
Declaração
de protótipo
int soma(int x, int y) {
return x+y;
}
int main() {
int x = soma(4,5); /* OK! */
int y = mult(4,5); /* Ok também! */
}
Definição
int mult(int x, int y) { da função
return x*y;
}
Rômulo C. Silva
Arquivos de cabeçalhos (Header)
Possuem extensão .h
Contém SOMENTE declarações de
protótipos de funções
Permite a criação de bibliotecas (funções
que serão usadas em vários programas)
Declara(m)-se o(s) protótipo(s) em um .h
Define(m)-se a função ou funções em um
arquivo separado
Inclui-se o arquivo .h no programa que irá usar
a função usando a diretiva #include
Rômulo C. Silva
Arquivos de cabeçalho - exemplo
/* Arquivo: minhafuncao.h */
int soma(int x, int y);
/* Arquivo: minhafuncao.c */
int soma(int x, int y) {
return x+y;
}
/*Arquivo: prog.c */
#include “minhafuncao.h”
int main() {
int x = soma(5,7);
}
Rômulo C. Silva
Escopo de variáveis
Locais:
Declaradas dentro de uma função: são conhecidas apenas
na própria função
Declaradas dentro de um bloco: conhecidas apenas dentro
do bloco
Os parâmetros formais são tratados como variáveis locais
Globais:
Declaradas fora de todas as funções do programa:
conhecidas em todo o escopo do programa.
int a,b;
void func1(int x) { Variáveis globais
printf(“%d”, x + a);
} Variável local
Rômulo C. Silva
Linguagem C - Diretivas de
Compilação
Analisadas pelo pré-processador de C
Lê o código fonte e gera um código fonte
expandido antes de proceder à compilação
Indicadas pelo operador #
Principais diretivas:
#include
#define
#ifdef
#ifndef
#endif
#undef
Rômulo C. Silva
Diretivas de Compilação -
#include
#include
#include “nome_do_arquivo”
#include <nome_do_arquivo>
“ “ (aspas) usadas quando o arquivo se
encontra no diretório de trabalho ou se
deseja indicar o caminho completo
< > são usados se estiver no caminho pré-
especificado pelo compilador, como é o
caso das bibliotecas padrão do C (stdio.h,
string.h, etc.)
Rômulo C. Silva
Diretivas de compilação -
#define
#define nomedamacro seq_caracteres
Cria uma macro com o nome especificado tal
que em todo ponto do código onde aparecer
uma referência a ela, será substituída
LITERALMENTE pela seqüência de caracteres
correspondente
Ex.:
#define PI 3.14
será substituído
por 3.14 antes da
void main() { compilação
float x = 4*PI;
}
Rômulo C. Silva
Diretivas de compilação -
#define
permite a utilização de parâmetros na
macro
Obs.: não pode haver espaços em branco
entre o nome da macros e os argumentos
Ex.:
#define PRINT(X) printf(“%d\n”, X);
void main() {
int a =4;
PRINT(a);
}
Rômulo C. Silva
Diretivas de compilação -
#define
CUIDADO!!!: a diretiva #define faz
substituição LITERAL
Rômulo C. Silva
Diretivas de Compilação - #undef
#undef nomedamacro
A partir desse ponto a macro não será mais conhecida e
portanto não pode mais ser usada
Ex.:
#define LINHA 30
void func() {
printf(“%d\n”, LINHA); /* OK!!! */
}
#undef LINHA
void main() {
int z = LINHA; /* erro de compilação!!!
*/
}
Rômulo C. Silva
Diretivas de compilação - #ifdef
e #endif
Sintaxe:
#ifdef nomedamacro
declaracoes
#endif
As declarações entre #ifdef e #endif
serão compiladas somente se
nomedamacro estiver definida.
Rômulo C. Silva
Diretivas de compilação - #ifndef
e #endif
Sintaxe:
#ifndef nomedamacro
declaracoes
#endif
Faz o contrário da diretiva #ifdef
Rômulo C. Silva
Diretivas de compilação - #if e
#else
Sintaxe:
#if expressao_constante
declaracoes1
#else
declaracoes2
#endif
A parte #else é opcional
Na expressão constante não é permitido o
uso de variáveis
declaracoes1 é compilada se a expressão
constante for verdadeira (diferente de zero)
Rômulo C. Silva
Diretivas de compilação -
exemplo
/* Arquivo: minhasfuncoes.h */
#ifndef MINHASFUNCOES_H
#define MINHASFUNCOES_H
void func(int x, int y);
#endif
Rômulo C. Silva
Linguagem C- Arquivos
Dispositivos de entrada e saída (discos,
impressoras, terminais, teclados) são
tratados como arquivos em C.
Rômulo C. Silva
Arquivos – principais funções
FILE* fopen(char* nomeArq, char* modo)
nomeArq deve ser um nome válido no sistema
operacional destino
modo indica quais serão as operações válidas
sobre o arquivo
A função retorna um ponteiro para arquivo
(handle)
No caso de erro a função retorna um ponteiro
nul (NULL)
Rômulo C. Silva
Arquivos – Modo de abertura
“r”: abre arquivo texto para leitura. O arquivo deve existir
antes de ser aberto.
“w”: abre arquivo texto para escrita. Se não existir será
criado. Se existir, o contéudo será apagado.
“a”: abre arquivo texto para escrita no final (“append”)
“rb”:mesmo que r, só que arquivo binário
“wb”: mesmo que w, só que arquivo binário
“ab”: mesmo que a, só que arquivo binário
“r+”: abre arquivo texto para leitura e gravação. O arquivo
deve existir e pode ser modificado.
“w+”: abre arquivo texto para leitura e gravação. Se arquivo
não existir, será criado.
“a+”: abre arquivo texto para leitura e gravação. Os dados
são adicionados no fim (“append”).
“r+b”: mesmo que r+ para arquivo binário
“w+b”: mesmo que w+ para arquivo binário
“a+b”: mesmqo que a+ para arquivo binário
Rômulo C. Silva
Arquivos – principais funções
Após o uso do arquivo, ele deve ser
fechado com a função
int fclose(FILE* fp)
Rômulo C. Silva
Arquivos – funções principais
Escrita de caracteres:
int putc(int ch, FILE* fp)
Leitura de caracteres:
int getc(FILE* fp)
Teste de fim de arquivo:
int feof(FILE* fp)
• Retorna valor diferente de zero se chegou ao fim do
arquivo.
Ler uma string:
char* fgets(char *str, int tam, FILE* fp)
Escrever uma string:
char *fputs(char *str, FILE* fp)
Rômulo C. Silva
Arquivos – funções principais
Leitura de bloco de dados:
unsigned fread(void* buffer, int
nro_bytes, int count, FILE* fp)
• buffer: região de meória onde os dados serão
armazenados
• nro_bytes: número de bytes lidos por unidade
• int count: quantidade de unidades a serem lidas
• Função retorna o número de unidades efetivamente lidas
Escrita de bloco de dados:
unsigned fwrite(void* buffer, int
nro_bytes, int count, FILE* fp)
• parâmetros similares aos de fread, porém para escrita
Rômulo C. Silva
Arquivos - exemplo
void main() {
FILE* fp = fopen(“arqteste.txt”, “a+”);
if(!fp) {
char str[50];
printf(“digite algo:\n“);
gets(str); /* lê do teclado */
fputs(str,fp); /* escreve no arquivo */
fclose(fp); /* fecha o arquivo */
}
}
Rômulo C. Silva
Arquivos – acesso randômico
int fseek(FILE* fp, long nro_bytes,
int origem)
Move a posição corrente nro_bytes a partir de
um ponto especificado (origem)
A origem pode ser:
• SEEK_SET: a partir do início do arquivo. Corresponde ao
valor 0 (zero)
• SEEK_CUR: posição corrente. Corresponde ao valor 1.
• SEEK_END: fim do arquivo. Corresponde ao valor 2
void rewind(FILE* fp)
Retorna a posição corrente para o início do
arquivo.
Rômulo C. Silva
Arquivos – outra funções
int fprintf(FILE* fp, char* str, …)
Semelhante a printf, porém escreve em um
arquivo
Rômulo C. Silva
Arquivos – outro exemplo
struct pessoa {
char nome[40];
int idade;
}; endereco da estrutura p
void main() {
struct pessoa p;
strcpy(p.nome, “Joao”);
p.idade = 25;
FILE* fp = fopen(“arquivoPessoa.dat”, “w+b”);
if(!fp) {
fwrite(&p, sizeof(struct pessoa), 1, fp);
}
}
quantidade de registros
Rômulo C. Silva
Arquivos – fluxos padrão
No início da execução de um programa são
abertos automaticamente alguns arquivos
especiais:
stdin: entrada padrão (geralmente teclado)
stdout: saída padrão (geralmente o vídeo)
stderr: saída de erro padrão (geralmente o
vídeo)
stdaux: dispositivo de saída auxiliar (em alguns
sistemas, associado à porta serial)
stdprn: dispositivo de impressão padrão (em
alguns sistemas, associado à porta paralela)
Rômulo C. Silva
Arquivos – fluxos padrão -
exemplo
void main() {
char str[50];
printf(“Digite algo: \n”);
fgets(str,49, stdin); /* lê da entrada padrão */
fputs(str,stdout); /* escreve na saída padrão */
}
Rômulo C. Silva
Estruturas (struct)
Agrupa várias variáveis em uma só
Semelhante ao record (registro) em Pascal
Sintaxe:
struct nome_estrutura {
tipo1 campo1;
tipo2 campo2;
...
tipoN campoN;
} var1, var2, …, varM;
Rômulo C. Silva
Estruturas - exemplo
struct endereco {
char rua[50];
char bairro[50];
int numero;
long int CEP;
char UF[3];
};
void main() {
struct endereco a;
strcpy(a.rua, “Av. Brasil”);
strcpy(a.bairro, “centro”);
a.numero = 1111;
a.CEP = 85856000;
strcpy(a.UF,”PR”);
}
Rômulo C. Silva
Estruturas
Estruturas podem fazer parte de outras.
Ex.:
struct endereco {
char rua[50];
char bairro[50];
int numero;
long int CEP;
char UF[3];
};
struct pessoa {
char nome[40];
char dataNascimento[11];
struct endereco end;
};
Rômulo C. Silva
Estruturas e Matrizes - exemplo
struct endereco {
char rua[50];
char bairro[50];
int numero;
long int CEP;
char UF[3];
};
struct pessoa {
char nome[40];
char dataNascimento[11];
struct endereco end;
};
void main() {
struct pessoa vetPessoas[100];
strcpy(vetPessoas[2].end.rua, “Av. Brasil”);
vetPessoas[2].end.numero = 1111;
}
Rômulo C. Silva
Estruturas - atribuição
A atribuição entre duas variáveis do tipo
estrutura efetua uma cópia campo a campo
Rômulo C. Silva
Estruturas – atribuição -
exemplo
struct endereco {
char rua[50];
char bairro[50];
int numero;
long int CEP;
char UF[3];
};
void main() {
struct endereco end1, end2;
... /* algum código onde end1 assume algum valor */
end2 = end1;
strcpy(end2.rua, “Rui Barbosa”); /* end1.rua agora
também aponta para “Rui Barbosa” !!! */
}
Rômulo C. Silva
Uniões (union)
Permite uma mesma localização de memória seja
ocupada por diferentes variáveis
Sintaxe:
union nome_uniao {
tipo1 campo1;
tipo2 campo2;
...
tipoN campoN;
} var1, var2, …, varM;
A região de memória associada à união será
ocupada por campo1 ou campo2 ou ... campoN
exclusivamente.
Rômulo C. Silva
Uniões - exemplo
union angulo {
int graus;
float radianos
};
void main(){
union angulo x;
x.graus = 90;
union angulo y;
y.radianos = 3.14156/2;
printf(“angulo x em graus: %d“, x.graus);
printf(“angulo y em radianos: %f”, y.radianos);
}
Rômulo C. Silva
Enumerações
Cria um tipo onde os valores que as
variáveis podem assumir estão pré-
definidos
Sintaxe:
enum nome_enumeracao {val1, val2, …, valN} var1,var2,
varM;
nome_enumeracao é tratado como sendo do
tipo int
val1 é associado ao valor 0 (zero)
val2 é associado ao valor 1 e assim por
diante.
Rômulo C. Silva
Enumerações - exemplo
void main() {
dia_semana d1 = quarta;
dia_semana d2 = domingo;
printf(“dia da semana: %d”, d1);
}
Rômulo C. Silva
Modificadores de variáveis
const
faz com que a variável não possa ser modificada no
programa.
Ex.:
const PI = 3.1415;
extern
indica que a variável estará declarada em outro arquivo,
mas que será usada no arquivo atual.
Ex.:
extern int nro_pessoas;
static
Em variável global: não serão conhecidas em outros
módulos (isolamento)
Em variável local: permite que uma chamada subseqüente
à função onde está definida guarde o valor que a variável
tinha na chamada anterior.
Rômulo C. Silva
Modificadores de Variáveis -
exemplo
const PI = 3.14156;
extern int total; /* variável definida em
outro arquivo */
Inicialização é
executada apenas
void func() { na primeira chamada
static int x = 0; da função
x++;
printf(“%d”, x);
}
void main() {
func();/* imprime o valor 1 na tela */
func(); /* imprime o valor 2 na tela */
}
Rômulo C. Silva
Alocação dinâmica
Permite o programador alocar memória para as
variáveis em tempo de execução.
Útil quando não se sabe exatamente quanto de
memória será necessária para determinada
estrutura ou matriz
Funções da biblioteca stdlib.h:
void *malloc(unsigned int qtd_bytes)
• Aloca qtd_bytes, retornando um ponteiro para o início da área
alocada
• void * pode ser atribuído a uma variável ponteiro para qualquer
tipo.
void *calloc(unsigned int num, unsigned int tam)
• Aloca num unidades de tamanho tam
Rômulo C. Silva
Alocação Dinâmica - liberação
Rômulo C. Silva
Alocação Dinâmica - exemplo
void main() {
int qtd = 4;
int *p = malloc(qtd*sizeof(int));
p[0] = 3;
p[1] = 5; operador sizeof retorna
o tamanho em bytes de
p[2] = 9; um tipo
p[3] = 7;
free(p);
libera a memória alocada
} previamente
Rômulo C. Silva
Alocação Dinâmica e Matrizes
Matrizes podem ser alocadas dinamicamente (pois são ponteiros).
void main() {
int ** mat;/* ponteiro para ponteiro */ aloca qtdLinhas
int qtdLinhas; do tipo ponteiro
int qtdColunas; para int
printf(“Digite o número de linhas: “);
scanf(“%d”, &qtdLinhas);
printf(“Digite o número de colunas: “);
scanf(“%d”, &qtdColunas);
mat = malloc(qtdLinhas*sizeof(int*));
int i;
for(i = 0; i < qtdLinhas; i++)
mat[i] = malloc(qtdColunas*sizeof(int));
...
for(i = 0; i < qtdLinhas; i++) aloca qtdColunas
free(mat[i]);
do tipo int para
free(mat);
} cada linha
Rômulo C. Silva
Ponteiros para estrutura -
exemplo
struct pessoa {
char nome[40];
int idade;
};
void main() {
struct pessoa *ptr = malloc(sizeof(struct pessoa));
strcpy(ptr->nome,”Joao”);
ptr->idade = 25;
}
Rômulo C. Silva
Ponteiros para Funções
Em C, funções também são tratadas como
ponteiros.
É possível declarar ponteiros para funções
explicitamente
Útil de implementação de callbacks
(funções que tipicamente tratam eventos)
Sintaxe:
tipo_retorno (*nome_ponteiro_funcao)(lista_parametros);
Rômulo C. Silva
Ponteiros para Funções -
exemplo
int soma(int x, int y) {
return x+y;
}
int mult(int x, int y) {
return x*y;
}
void main() {
int a = 5, b = 7;
int (*f)(int,int);/* f é um ponteiro para função de
protótipo int (int, int) */
f = soma;
int resultado1 = (*f)(a,b); /* invoca soma(a,b) */
f = mult;
int resultado2 = (*f)(a,b); /* invoca mult(a,b) */
}
Rômulo C. Silva
Comando typedef
Permite definir um novo nome para um tipo já definido
Sintaxe:
typedef tipo_ja_definido novo_nome_tipo;
Ex.:
typedef int inteiro;
typedef struct estr_pessoa {
char nome[50];
int idade;
} Pessoa;
typedef int(*PONTEIRO_FUNCAO)(int,int);
void main() {
inteiro x = 4;
Pessoa p1;
PONTEIRO_FUNCAO fp;
...
}
Rômulo C. Silva
Bibliografia
Curso de Linguagem C / UFMG . Renato
Cardoso Mesquita.
Rômulo C. Silva