You are on page 1of 147

Linguagem C

Prof. Rômulo Silva

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

 Usada para reescrever o sistema Unix em 1973


 Ainda hoje (2008), a maioria dos programas e utilitários do Unix
estão escritos em C.

 Em 1980 já existiam várias versões de compiladores C


oferecidas por diversas empresas

 Padronizada a partir de 1983 pela ANSI (American National


Standards Institute)

 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

 “Linkar” (ligar) o código objeto


• Gera arquivo executável
 Para a maioria das plataformas (Sist.
Operacionais), existem ferramentas que integram
todas as fases

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

unsigned char 1 0 a 255

signed 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

signed int 4 -2.147.483.648 a


2.147.483.647
short int 4 -32.768 a 32.767

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

long int 4 -2.147.483.648 a


2.147.483.647
signed long int 4 -2.147.483.648 a
2.147.483.647
unsigned long int 4 0 a 4.294.967.295

float 4 3.4E-38 a 3.4E+38

double 8 10 dígitos de precisão

long double 10 10 dígitos de precisão

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)

 Hexadecimais: números representado na base 16.


São indicados com a inclusão de 0x ou 0X no
início.
 0xF (15 na base decimal)
 0x3A (58 na base decimal)
 0X27 (39 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)

 Pode ser indicada através do código ASCII


em octal no formato ‘\0ddd’
 ‘\0141’ (correponde 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.

 O programador não pode ser definir


identificadores próprios usando as palavras-
reservadas.
 Em torno de 100 palavras-reservadas
Rômulo C. Silva
Linguagem C – palavras
reservadas
 Especificadores e modificadores de tipo:
 int, long, double, float, void, short, unsigned,
etc.
 Diretivas para o pré-processador:
 #include, #define, #ifdef, #ifndef, #endif, etc.
 Comandos para controle de fluxo:
 for, while, do, case, switch, continue, break,
default, etc.
 Delimitadores:
 ; [] () {}
 Operadores:
 && || + - / * %

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;

 Locais permitidos para declaração de variáveis:


 Fora de todas as funções (variáveis globais)
 Dentro de um bloco de código delimitado por {}
 Parâmetros de funções.

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

main() { pular uma linha


int x = 20;
char ch = ‘A’
float y = 5.0;
printf(“valor de x: %d\n ch: %c\n y: %f”, x,ch,y);
}

 Número de argumentos de printf é variável

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

 0 (zero) é considerado falso


 Qualquer valor diferente de 0 (zero) é considerado
verdadeiro
 Exemplos:
 2 && 3 resulta em 1 (verdadeiro)
 3 || 4 resulta em 1 (verdadeiro)
 0 && 1 resulta em 0 (falso)
 !3 resulta em 0 (falso)
 !0 resulta em 1 (verdadeiro)

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”);

if(y > x)/* será avaliado como verdadeiro */


printf(“y é maior que x”);
else
printf(“y é menor ou igual a x”);

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)

 Semelhante ao comando while, porém o teste é


feito após a execução de cmd.
 cmd é executado ao menos uma vez.

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

/* exemplo de laço infinito */ sem inicialização,


for(;;) sem teste e
sem incremento
printf(“isto é um laço infinito”);

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

 Se houver um comando break, ele deixa


switch imediatamente. Senão executa
todos os comandos após encontrar a
constante procurada.

 default é executado se nenhuma opção


dos case’s unifica com o valor de expr.
Rômulo C. Silva
Comando switch - exemplo
int x;
... /* x assume algum valor entre a declaração e
o switch */
switch(x) {
case 1:
printf(“opcao 1 foi escolhida”); break;
case 2:
printf(“opcao 2 foi escolhida”); break;
case 3:
printf(“opcao 3 foi escolhida”); break;
default:
printf(“opcao invalida!”); break;
}

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)

 Índice do vetor sempre começa em 0 (zero)


 Para acessar um caracter específico, basta-
se indexar o vetor. Assim, suponha uma
string char str[50]; :
 str[0] acessa o primeiro caracter da string
 str[1] acessa o segundo caracter da string
 Strings podem ser inicializadas por
constantes:
char str[50] = “Foz do Iguaçu”;

posições ocupadas: de 0 a 13, as demais


contêm valores indeterminados (“lixo”)

Rômulo C. Silva
Linguagem C - Strings
 A biblioteca string.h contém funções utilitárias
para manipulação de strings

 A cópia de uma variável do tipo string para outra


deve ser feita caracter a caracter ou utilizar a
função strcpy, NUNCA através da atribuição.

 É responsabilidade do programador garantir que a


quantidade de posições seja suficiente para conter
a string copiada.

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

char str1[20] = “cadeia 1”;


char str2[10] = “cadeia 2”;
strcat(str1,str2); // concatena str1 e str2
if(strcmp(str2, “cadeia 2”)==0)
printf(“str2 contem cadeia 2”);
else
printf(“str2 contem outra cadeia”);

Rômulo C. Silva
Linguagem C - Strings
 Comprimento da string: função strlen
 O terminador nulo NÃO é contado

char str1[20] = “cadeia exemplo”;


int tam = strlen(str1);
printf(“tamanho = %d“, tam);// imprimirá 14

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.:

int vet[5] = {27, 12, 9, 13, 11};


int mat[2][3] = {1,2,3,4,5,6};
char str1[6] = {‘M’, ‘a’, ‘r’, ‘i’, ‘a’, ‘\0’};
char str2[8] = “cadeia2”;
char matStr[3][15] = { “Pedro”, “Joao”, “Carla”};
printf(“%s”, matStr[1]); /* imprimirá Joao */

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”;

int mat[][2] = {5,7,8,2,9,6,7,4,5,3,5,2,11,


17,23,19}; / * serão 8 linhas e 2 colunas */

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 &

 O operador (*) pode ser usado para


acessar/alterar o valor armezanado na área
apontada pelo ponteiro (conteúdo da
posição de memória).

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

ptrx passa apontar para a mesma


posição que ptry aponta

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

 Dado um ponteiro ptr para algum tipo:


 ptr = ptr + 15; ou ptr += 15; avança 15
posições
 *(ptr+15) acessa o valor que está 15 posições
adiante sem alterar o valor de ptr.

 Os operadores ++ e -- têm precedência


sobre o operador *

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++);

ptr passa apontar uma posição


à frente do endereço de x. Em seguida
y recebe o valor armazenado na
nova posição.

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]

py = &vet[0]; pz guarda o endereço


de vet[3]
pz = vet+3;
elem = *(vet+5); elem recebe o valor
de vet[5]
printf(“%d”, py[2]);
imprime vet[2] na tela
Rômulo C. Silva
Linguagem C – Ponteiros e
Matrizes
 Dado um vetor vet:
 vet corresponde ao endereço do elemento de
índice 0 (zero)
 vet+i corresponde ao endereço do elemento
vet[i]
 *(vet+i) corresponde ao valor armazenado em
vet[i]
 Dado um ponteiro p:
 p[i] acessa o conteúdo da posição i
 *p acessa o conteúdo da posição 0 (zero)
 *(p+i) acessa o conteúdo de p[i]

Rômulo C. Silva
Linguagem C – Matrizes e
Ponteiros
 Matrizes e ponteiros podem ser combinados
de várias maneiras:

int *v[5]; vetor de ponteiros


para int
int x = 7;
int y = 9;
v[3] recebe o
int z; endereço da variável x
v[3] = &x;
v[2] = &y; z agora vale 7

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

 Passagem por referência pode ser simulada


através do uso de ponteiros:
 O endereço das variáveis são passadas para a
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
}

void troca(int *x, int *y) {


int z = *x;
*x = *y;
*y = z; passagem por valor
}
void main() {
int x=2, y=3;
int s = soma(x,y);
troca(&x,&y);
} passagem por valor
do endereço das variáveis
Rômulo C. Silva
Funções – passagem de
parâmetros
 Vetores e matrizes são passados por referência, já
que são tratados como ponteiros.
 Ex.:
void alteraVet(int vet[], int pos, int val) {
vet[pos] = val;
}
void main() {
int m[] = {0,1,2,3,4,5,6,7};
alteraVet(m,3,50);
}
após essa instrução
m[] = {0,1,2,50,4,5,6,7}

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]);
}

No shell do sistema operacional:


C:> prog kkk a 45
nome deste programa: prog
argumento = kkk
argumento = a
argumento = 45
Rômulo C. Silva
Função main
 Pode ter retorno do tipo int ou void:
 int
• Retorna um número inteiro significando um código de
erro para o sistema operacional
– 0 (zero) indica sucesso
– Outro valor indica erro

 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

 Protótipo: assinatura da função

 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.

 Obs.: se uma função declara uma variável local


com mesmo nome de uma variável global, a
preferência será dada para a variável local dentro
da função.
Rômulo C. Silva
Escopo de variáveis - exemplo

int a,b;
void func1(int x) { Variáveis globais
printf(“%d”, x + a);
} Variável local

void func2(int y, int b) {


int a = 5;
printf(“%d”, y + a + b);
}
void main() {
a = 7; /* variável global */
b = 9; /* variável global */
func1(3);
func2(3,2);
}

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

#define SQR(X) X*X


será subsituída por
a+b*a+b que é diferente
void main() { de (a+b)*(a+b)
int a = 2;
int b = 3;
int c = SQR(a+b);
}
Rômulo C. Silva
Diretivas de Compilação -
#define
 Solução para evitar problemas com
#define: colocar parênteses
 Ex.:

#define SQR(X) (X)*(X)

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

/*Arquivo: prog.c */ evita múltiplas


inclusões do arquivo
#include <stdio.h>
#include “minhasfuncoes.h”
...

Rômulo C. Silva
Linguagem C- Arquivos
 Dispositivos de entrada e saída (discos,
impressoras, terminais, teclados) são
tratados como arquivos em C.

 Arquivos propriamente ditos são


manipulado via ponteiros para arquivo
(FILE *)
 Definido em stdio.h

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)

 A função retorna 0 (zero) em caso de


sucesso.

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

 int fscanf(FILE* fp, char* str, …)


 Semelhante a scanf, porém lê de 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

 Cuidado!!!: campos do tipo string são


ponteiros. Não é feita uma cópia do
conteúdo e sim apenas do ponteiro
(endereço de memória).

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

enum dia_semana {segunda, terca, quarta,


quinta, sexta, sabado, domingo};

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

 Liberação da memória alocada:


 void free(void *p)

 Todas memória alocada usando malloc e


calloc só podem ser liberadas através da
função free.

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;
}

ptr->idade equivale a (*ptr).idade

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.

 Introdução à linguagem C. Centro de


Computação – Unicamp

 The C++ Programming Language.


Bjarne Stroustrup.

Rômulo C. Silva

You might also like