Baixe o app para aproveitar ainda mais
Prévia do material em texto
Funções INF1005 – Programação I – 33B Prof. Gustavo Moreira gmoreira@inf.puc-rio.br 1 funções tópicos como definir uma função assinatura (protótipo) de uma função pilha de execuçãopilha de execução escopo de variáveis referência Capítulo 3 da apostila 2 o que são funções? 3 funções matemáticas Função é uma relação de um ou vários valores de argumentos de entrada em um ÚNICO resultado de saída. y z 4 O conjunto de todos os valores de entrada de uma função é chamado de DOMÍNIO da função. O conjunto de todos os resultados é chamado de IMAGEM da função. Normalmente a IMAGEM é um subconjunto de um conjunto de resultados possíveis chamado de CONTRADOMÍNIO. A notação é: f: Domínio→Contradomínio. Para Fig I temos e para Fig II temos , onde R é o conjunto dos números reais. x y x x = 2 y = 2→ z = 8 z = f(x,y) = x2+y2 f(x) = x2 x = 2 → f(x) = 4 Fig I Fig II f: R → R f: R × R → R funções e procedimentos máquina funcionalmáquina funcionalmáquina funcionalmáquina funcional: máquina que processa valores de entrada e retorna um valor de saída 1 2 valores de entrada máquina que processa valores de entrada, retorna um valor de saída e produz um efeitoproduz um efeitoproduz um efeitoproduz um efeito 1 2 valores de entrada máquina máquina máquina máquina procedimentalprocedimentalprocedimentalprocedimental: máquina que processa valores de entrada e produz um produz um produz um produz um efeito (mas não retorna nenhum valor de saída) 1 2 valores de entrada 5 5 valor de saída f(x,y) = x2+y2 5 valor de saída g(x,y) = x2+y2 h(x,y) = x2+y2 Em C, funções e procedimentos são chamados simplesmente de funçõesfunçõesfunçõesfunções. funções e procedimentos 6 por que e como usarcomo usar funções? 7 "chamando" (usando) funções ... int main(void) { float nota1, nota2, nota3; float media; nota1 = le_nota(); nota2 = le_nota(); nota3 = le_nota(); media = calc_media(nota1, nota2, nota3); imprime_media(media); return 0; 8 return 0; } As funções le_notale_notale_notale_nota, calc_mediacalc_mediacalc_mediacalc_media e imprime_mediaimprime_mediaimprime_mediaimprime_media precisam ser definidas pelo programador. como definir uma função 9 forma geral para definir funções tipo_retornado nome_da_função (lista de parâmetros...) { corpo_da_função } tipo retornado sintaxesintaxesintaxesintaxe 10 float converte (float c) { float f; f = 1.8*c + 32; return f; } nome da função parâmetro(s) corpo da função retorno do valor declaração de variáveis sintaxesintaxesintaxesintaxe (forma da função) semânticasemânticasemânticasemântica (funcionalidade ou comportamento: o que a função faz) funções alternativas "equivalentes" para cálculo de média float calc_media (float a, float b, float c) /* definição da função */ { float soma, media; soma = a + b + c; media = soma/3; return media; } float calc_media (float a, float b, float c) /* definição da função */ { float soma; soma = a + b + c; A B 11 soma = a + b + c; return soma/3; } float calc_media (float a, float b, float c) /* definição da função */ { return (a + b + c)/3; } int main(void) { float media = calc_media (3.0F, 4.0F, 8.0F); printf("A media e': %.2f\n", media); return 0; } 04_01_func_media.c chamadachamadachamadachamada da função printfprintfprintfprintf também é função C Ao chamar a função calc_media, os valoresvaloresvaloresvalores passados como parâmetro (3.0F, 4.0F e 8.0F) são copiadoscopiadoscopiadoscopiados para os parâmetros da função, nananana respectivarespectivarespectivarespectiva ordemordemordemordem. 1 float calc_media (float a, float b, float c) { float res; res = (a + b + c)/3; return res; } int main(void) { float media; media = calc_media (3.0F, 4.0F, 8.0F); O que acontece quando uma função é chamada por outra? 3.0F 4.0F 8.0F media = calc_media (3.0F, 4.0F, 8.0F); printf("A media e': %.2f\n", media); return 0; } 12 media = 5.0F; res = (3.0F + 4.0F + 8.0F) / 3;A função calc_media executa:2 media = calc_media (3.0F, 4.0F, 8.0F); res = 5.0F; A função calc_media retorna o valorvalorvalorvalor armazenado na variável res (que deve ser do tipo float) para função que a chamou: 3 return res; return 5.0F; 4 Na função main, o valor retornado é atribuído à variável media: 5 O restante do programa é executado, imprimindo a saída: A média é 5.00. usando funções como parâmetros para outras funções ... int main(void) { float nota1, nota2, nota3; float media; nota1 = le_nota(); nota2 = le_nota(); nota3 = le_nota(); media = calc_media(nota1, nota2, nota3); imprime_media(media); return 0; } 13 ... int main(void) { float media; media = calc_media(le_nota(), le_nota(), le_nota()); imprime_media(media); return 0; } ... int main(void) { imprime_media(calc_media(le_nota(), le_nota(), le_nota())); return 0; } dúvidas?dúvidas? 14 media = 5.0F;3b float calc_media (float a, float b, float c) { return (a + b + c)/3; } int main(void) { float media; media = calc_media (3.0F, 4.0F, 8.0F); printf("A media e': %.2f\n", media); return 0; } exemplo – pilha de execução 1 3 4 2b 5 } 15 1. main, após declaração da variável media main media ??? 2. entrou na função calc_media calc_ media c 8.0F b 4.0F a 3.0F main media ??? 3. saiu de calc_media, retornando 5.0F main media ??? 5.0F 4. atribuiu valor retornado à variável média main media 5.0F dúvidas?A media e': 5.00 5. exibiu resultado Que dados uma função “enxerga”? comunicação entre funções: � funções são independentes entre si � uma função não enxerga as variáveis de uma outra � a transferência de dados entre funções é feita através de � parâmetros (passagem por valor) � valor de retorno da função chamada variáveis locais a uma função:variáveis locais a uma função: � parâmetros (declarados no protótipo da função) e variáveis declaradas dentro da função � não existem fora da função � são criadas cada vez que a função é executada � deixam de existir quando a execução da função terminar de executar 16 exemplo float calc_media (float a, float b, float c) { return (a + b + c)/3; } int main(void) { float media; media = calc_media (3.0F, 4.0F, 8.0F); printf("A media e': %.2f\n", media); return 0; } 17 float media (float a, float b, float c) { return (a + b + c)/3; } int main(void) { float media; media = media (3.0F, 4.0F, 8.0F); printf("A media e': %.2f\n", media); return 0; } Cuidado para não dar o mesmo nome a elementos diferentes! uso de função int subt (int a, int b) { return a - b; } int main (void) { int a = 3, b = 5, x = 20, y = 12; printf("%d - %d = %d\n", b, a, subt(b, a)); printf("%d - %d = %d\n", x, y, a = subt(x, y)); printf("a: %d\n", a); return 0; EX. 01 18 return 0; } Qual é a saída desse programa? 04_02_func_sub.c int subt (int a, int b) { return a - b; } int main (void) { int a = 3, b = 5, x = 20, y = 12; printf("%d - %d = %d\n", b, a, subt(b, a)); printf("%d - %d = %d\n", x, y, a = subt(x, y)); printf("a: %d\n", a); return 0; uso de função EX. 01 1. main, após declarações e inicializações y 12 x 20 b 5 main a 3 1 2 3 4 5 6 7 8 9 return 0; } 19 main a 3 2. chamou subt(b,a) b 3 subt a 5 y 12 x 20 b 5 main a 3 3. saiu de subt, retornando2 y 12 x 20 b 5 main a 3 2 4. imprime 5 – 3 = 2 5. chamou subt(x,y) b 12 subt a 20 y 12 x 20 b 5 main a 3 6. saiu de subt, retornando 8 y 12 x 20 b 5 main a 3 8 8. imprime 20 – 12 = 8 9. imprime a: 8 7. atribui 8 a a y 12 x 20 b 5 main a 8 uso de função int subt (int a, int b) { return a - b; } int main (void) { int a = 3, b = 5, x = 20, y = 12; printf("%d - %d = %d\n", b, a, subt(b, a)); printf("%d - %d = %d\n", x, y, a = subt(x, y)); printf("a: %d\n", a); return 0; EX. 01 20 return 0; } Qual é a saída desse programa? 5 – 3 = 2 20 – 12 = 8 a: 8 04_02_func_sub.c dúvidas?dúvidas? 21 função sem valor de retorno #include <stdio.h> void imprime_media (int a, int b) { float med = (a + b) / 2; printf("A media e': %f\n", med); } int main (void) { int x, y; Esta função calcula a média corretamente? palavra-chave voidvoidvoidvoid indica que não há valor de retorno Dica: teste com imprime_media(4,5); 22 int x, y; printf("Digite dois numeros inteiros: "); scanf("%d%d", &x, &y); imprime_media(x, y); return 0; } 04_04a_func_no_return_err.c função sem valor de retorno #include <stdio.h> void imprime_media (int a, int b) { float med = (a + b) / 2; printf("A media e': %f\n", med); } int main (void) { int x, y; 23 int x, y; printf("Digite dois numeros inteiros: "); scanf("%d%d", &x, &y); imprime_media(x, y); return 0; } 04_04a_func_no_return_err.c função sem valor de retorno #include <stdio.h> void imprime_media (int a, int b) { float med = (a + b) / 2.0F; printf("A media e': %f\n", med); } int main (void) { int x, y; 24 int x, y; printf("Digite dois numeros inteiros: "); scanf("%d%d", &x, &y); imprime_media(x, y); return 0; } 04_04b_func_no_return_ok.c O trecho de código abaixo estaria correto? int med = imprime_media(5,8); Por quê? Por que não? dúvidas?dúvidas? 25 conversão de temperatura (ex 01) /* Converte temperatura de Celsius em Fahrenheit */ #include <stdio.h> /* inclui biblioteca padrão */ int main (void) { float cels; /* temperatura em Celsius */ float fahr; /* temperatura em Fahrenheit */ /* exibe instrução para usuário */ printf("Digite a temperatura em Celsius: "); /* lê do teclado temperatura em Celsius */ scanf("%f", &cels); /* calcula a conversão */ fahr = 1.8 * cels + 32; /* exibe na tela o resultado */ printf("Temperatura em Fahrenheit: %f", fahr); return 0; } 26 Digite a temperatura em Celsius: 0 Temperatura em Fahrenheit: 32.000000 03_01_conversao_temp.c conversão de temperatura (ex 01a) /* Converte temperatura de Celsius em Fahrenheit */ #include <stdio.h> float converte (float c) /* define função para conversão */ { float f; f = 1.8*c + 32; return f; } int main (void) { mesmo resultado que: return 1.8*c + 32; int main (void) { float cels; /* temperatura em Celsius */ float fahr; /* temperatura em Fahrenheit */ /* exibe instrução para usuário */ printf("Digite a temperatura em Celsius: "); /* lê do teclado temperatura em Celsius */ scanf("%f", &cels); /* calcula a conversão */ fahr = converte(cels); /* exibe na tela o resultado */ printf("Temperatura em Fahrenheit: %f", fahr); return 0; } 27 04_03_func_conv_temp.c conversão de temperatura (ex 01b) /* Converte temperatura de Celsius em Fahrenheit */ #include <stdio.h> float converte (float c) /* define função para conversão */ { return 1.8*c + 32; } int main (void) { float cels; /* temperatura em Celsius */ float fahr; /* temperatura em Fahrenheit */float fahr; /* temperatura em Fahrenheit */ /* exibe instrução para usuário */ printf("Digite a temperatura em Celsius: "); /* lê do teclado temperatura em Celsius */ scanf("%f", &cels); /* calcula a conversão */ fahr = converte(cels); /* exibe na tela o resultado */ printf("Temperatura em Fahrenheit: %f", fahr); return 0; } 28 conversão de temperatura (ex 01c) /* Converte temperatura de Celsius em Fahrenheit */ #include <stdio.h> float converte (float c) /* define função para conversão */ { return 1.8*c + 32; } int main (void) { float cels; /* temperatura em Celsius */ float fahr; /* temperatura em Fahrenheit */float fahr; /* temperatura em Fahrenheit */ /* exibe instrução para usuário */ printf("Digite a temperatura em Celsius: "); /* lê do teclado temperatura em Celsius */ scanf("%f", &cels); /* calcula a conversão */ fahr = converte(cels); /* exibe na tela o resultado */ printf("Temperatura em Fahrenheit: %f", converte(cels)); return 0; } 29 Ao encontrar uma função, o compilador precisa conhecer os tipos dos seus parâmetros e do valor retornado. conversão de temperatura (ex 01d) /* Converte temperatura de Celsius em Fahrenheit */ #include <stdio.h> float converte (float c); /* protótipo da função */ int main (void) { float cels; /* temperatura em Celsius */ /* exibe instrução para usuário */ printf("Digite a temperatura em Celsius: "); /* lê do teclado temperatura em Celsius */ scanf("%f", &cels); Ao encontrar uma função, o compilador precisa conhecer os tipos dos seus parâmetros 30 scanf("%f", &cels); /* calcula a conversão */ /* exibe na tela o resultado */ printf("Temperatura em Fahrenheit: %f", converte(cels)); return 0; } float converte (float c) /* definição da função de conversão */ { return 1.8*c + 32; } os tipos dos seus parâmetros e do valor retornado. A função propriamente dita pode ser definida depois. protótipo ou assinatura da função funções definidas antes da main: não precisam de protótipo /* definição: sem ; no final*/ float converte (float c) { ... } int main (void) funções definidas após a main: precisam de protótipo /* protótipo: com ; no final*/ float converte (float c); int main (void)int main (void) { ... t2 = converte (t1); ... } int main (void) { ... t2 = converte (t1); } /* definição: sem ; no final*/ float converte (float c) { ... } 31 conversão de temperatura (ex 01e) /* Converte temperatura de Celsius em Fahrenheit */ #include <stdio.h> float le_celsius(); /* protótipo da função */ float converte (float c); /* protótipo da função */ int main (void) { printf("Temperatura em Fahrenheit: %f", converte(le_celsius())); return 0; } Como fica a pilha de execução desse programa a cada passo? 32 float le_celsius() { /* definição da função de leitura do teclado */ float cels; /* declaração de variável local */ printf("Digite a temperatura em Celsius: "); /* instrução para o usuário */ scanf("%f", &cels); /* lê valor do teclado */ return cels; /* retorna valor lido */ } float converte (float c) /* definição da função de conversão */ { return 1.8*c + 32; /* calcula e retorna o valor convertido */ } 04_03_func_conv_temp_e.c dúvidas?dúvidas? 33 exemplo – cálculo de fatorial #include <stdio.h> int fat (int n); /* protótipo da função */ int main (void) /* função principal */ { int n; int r; printf("Digite um numero positivo: "); scanf("%d", &n); r = fat(n); /* chamada da função */ 34 r = fat(n); /* chamada da função */ printf("Fatorial = %d\n", r); return 0; /* retorno da main: 0 = execução OK */ } /* função para calcular o valor do fatorial */ int fat (int n) /* declaração da função */ { int f = 1; while (n > 0) f *= n--; return f; } 04_05_func_fatorial.c pilha de execução– cálculo de fatorial #include <stdio.h> int fat (int n) { int f = 1; while (n > 1) f *= n--; return f; } int main (void) { int n; 1. após decl. n e r main r ??? n ??? 2. após ler n main r ??? n 5 3. após chamar fat fat n 5 main r ??? n 5 5. iterando … f 5 6. iterando… f 20 7. iterando… f 60 3 567 8 9 suponha que o usuário digitou o número 5 4 4. após int f = 1; fat f 1 n 5 main r ??? n 5 cópia do valor passado como parâmetro 35 int n; int r; printf("Digite um numero positivo: "); scanf("%d", &n); r = fat(n); printf("Fatorial = %d\n", r); return 0; } 04_05_func_fatorial.c fat f 5 n 4 main r ??? n 5 fat f 20 n 3 main r ??? n 5 fat f 60 n 2 main r ??? n 5 8. iterando…fim fat f 120 n 1 main r ??? n 5 9. retorno de fat(n) main r ??? n 5 1 2 10 11 10. atrib. r=fat(n); main r 120 n 5 11. fim do programa 120 dúvidas?dúvidas? 36 04_13_stdio_printf.cfunções da biblioteca <stdio.h> int printf (formato, variáveis, …): escreve na tela int i = 3; printf("%d\n", i); alguns formatos: %c char %s : cadeia de caracteres %d int %u : unsigned int %ld: long int %f float %lf: double %e float (notação científica) %le: double (notação científica) %g float (formato mais curto: %f ou %e) %lg: double (formato mais curto) 3 %g float (formato mais curto: %f ou %e) %lg: double (formato mais curto) %x número em hexadecimal tamanhos, posições, alinhamento: %4d inteiro em 4 posições %-4d inteiro em 4 posições, alinhado à esquerda %04d inteiro em 4 posições, preenchidas com zeros à esquerda do valor %6.2f double (ou float) em 6 posições, com 2 casas decimais %% sinal de porcentagem alguns caracteres de escape: \n caractere de nova linha \" caractere " \t caractere de tabulação \\ caractere \ 37 printf - exemplos float a = 3, b = 3.5; int c = 3; printf("%6.2f\n", a); printf("%6.2f\n", b); 3 . 0 0 3 . 5 0 2 casas decimais, 6 casas no total printf("%6.2f\n", b); printf("%6d\n", c); printf("%-6d\n", c); printf("%06d\n", c); printf("%d\n", c); 38 3 . 5 0 3 3 3 total 0 0 0 0 0 3 funções da biblioteca <stdio.h> int scanf (formato, endereços, …) lê do teclado dados no formato especificado retorna o número de itens lidos int i, h, m; char letra; scanf("%d", &i); printf("numero digitado: %d\n", i); 04_15_stdio_scanf.c printf("numero digitado: %d\n", i); printf("digite a hora no formato hh:mm\n"); scanf("%d:%d", &h, &m); /* usuário deve digitar os :, como em 8:30 */ printf("%02d:%02d\n", h, m); scanf(" %c", &letra); printf("caractere digitado: %c\n", letra); 39 > 4 numero digitado: 4 digite a hora no formato hh:mm > 8:30 08:30 > a caractere digitado: a esse espaço faz ignorar "brancos" nessa posição da entrada (espaço, <tab>, <enter>) &x: endereço de x Por que scanf precisa do endereço de variáveis?Em C, funções recebem parâmetros porporporpor valorvalorvalorvalor (cópia) se um valor é modificado dentro da função, quando a função termina (desempilha), os valores originais se mantêm inalterados void somaprod(int a, int b, int soma, int prod) { soma = a+b; prod = a*b; } int main(void) { int s, p; 2 3 40 int s, p; somaprod (3, 5, s, p); printf("soma: %d \nproduto: %d\n", s, p); return 0; } 1 4 04_17_func_par_valor.c 1. após decl. main main p ? s ? 2. chamada de somaprod somaprod prod ? soma ? b 5 a 3 main p ? s ? 3. após os cálculos somaprod prod 15 soma 8 b 5 a 3 main p ? s ? 4. na volta para a main main p ? s ? soma: 751351 produto: -267762 (lixo) Por que scanf precisa do endereço de variáveis? funções podem receber endereços como parâmetro se uma função conhece o endereço de uma posição de memória, ela pode modificar o conteúdo dessa posição void somaprod(int a, int b, int* soma, int* prod) { /* muda o valor do que está no respectivo endereço */ *soma = a+b; *prod = a*b; } int main(void) { int s, p; 2 3 41 int s, p; somaprod (3, 5, &s, &p); /* passa valores 3 e 5 e endereços de s e p */ printf("soma: %d \nproduto: %d\n", s, p); return 0; } 1 1. após decl. main main p ? 108 s ? 104 2. chamada de somaprod somaprod prod 108 124 soma 104 120 b 5 116 a 3 112 main p ? 108 s ? 104 3. atrib. após cálculos somaprod prod 108 124 soma 104 120 b 5 116 a 3 112 main p 15 108 s 8 104 4. na volta para a main main p 15 108 s 8 104 4 04_19_func_par_ref.c soma: 8 produto: 15 5. após printf dúvidas?dúvidas? 42 exercício Escreva um programa que leia as dimensões (b,h,e,d) dessa peça, calcule e exiba a área e o volume desta peça (com furos cilíndricos). Escreva funções auxiliares quando necessário ou desejável. Lembrando: área de um retângulo: EX. 02 Ar = b x h área de um círculo: Ac = Π × r2 volume de um paralelepípedo: Vp = b x h x l volume de um cilindro: Vc = Π × r2 × h 43 escopo de umade uma variável 44 (onde a variável pode ser acessada) variável local escopo é o bloco em que a variável foi declarada if ( n > 0 ) { declaração da variável i 45 { int i; /* só pode declarar no início do bloco */ ... i = f(n); ... /* aqui já não pode declarar variáveis */ } ... /* a variável i já não existe neste ponto */ escopo da variável i variável global variável declarada fora das funções não faz parte da pilha de execução é visível por todas as funções existe enquanto o programa estiver sendo executado causa interdependência entre funções! NãoNãoNãoNão devedevedevedeve serserserser utilizadautilizadautilizadautilizada emememem ProgIProgIProgIProgI !!!! causa interdependência entre funções pode tornar código difícil de entender e reutilizar 46 #include <stdio.h> int s, p; /* declaração de variáveis globais */ void somaprod (int a, int b) { ... } int main (void) { ... } ! ! exemplo de programa #include <stdio.h> int s, p; /* declaração de variáveis globais */ void somaprod (int a, int b) { s = a + b; /* atribuição a variáveis globais */ p = a * b; } int main (void) { int x, y; /* declaração de variáveis locais */ 47 int x, y; /* declaração de variáveis locais */ /* fornece instrução aos usuários */ printf("Digite dois numeros: "); scanf("%d %d", &x, &y); /* lê número do teclado */ somaprod(x, y); /* calcula soma e produto */ /* exibe na tela o resultado */ printf("Soma: %d+%d=%d, Produto: %d*%d=%d \n", x, y, s, x, y, p); return 0; } Digite dois numeros: 2 3 Soma: 2+3=5, Produto: 2*3=6 04_09_escopo_var_g.c variável estática staticstaticstaticstatic int i; quando declarada no corpo de uma função: visível apenas naquela função utilizada quando é necessário recuperar o valor de uma variável atribuída na última vez que a função foi executada NãoNãoNãoNão precisaprecisaprecisaprecisa serserserser utilizadautilizadautilizadautilizada emememem ProgIProgIProgIProgI !!!! quando declarada fora de funções: visível apenas naquele módulo (arquivo .c) não é armazenada na pilha de execução: área de memória estática existe enquanto o programa estiver sendo executado 48 exemplo – variável estática #include <stdio.h> void imprime(void) { static int i = 1; printf("\n%d ", i++); } int main(void) { imprime();imprime(); printf("primeira linha"); imprime();printf("segunda linha"); imprime(); return 0; } 49 1 primeira linha 2 segunda linha 3 04_07_escopo_var.c resumo: tipos de variáveis quanto ao escopo tipotipotipotipo declaraçãodeclaraçãodeclaraçãodeclaração declaradadeclaradadeclaradadeclarada ondeondeondeonde escopoescopoescopoescopo ((((acessívelacessívelacessívelacessível de de de de ondeondeondeonde)))) global int a; fora de qualquer função (ínício do programa) todos os módulos do programa (outros módulos devem declará-la como externa); valor é sempre mantido local (ou automática) int a; dentro de um bloco somente no bloco; valor não é mantido estática em static int a; dentro de uma função alocada em área fixa da memória; 50 estática em função static int a; dentro de uma função alocada em área fixa da memória; valor é mantido durante toda a execução do programa estática no módulo static int a; fora de qualquer função apenas no módulo em que é declarada externa extern int a; fora de qualquer função, fazendo referência à variável global correspondente declarada em outro módulo todos os módulos do programa em que ela esteja declarada 04_07_escopo_var.c exemplo: escopo de variáveis #include <stdio.h> int i=10; static int j=10; void exemplo1() { int i = 5; int j = 15; printf("\t%2d %2d\n", i++, j--); } void exemplo2() { static int i=1; printf("\t%2d %2d\n", i++, j--); } DeveDeveDeveDeve----se se se se evitarevitarevitarevitar definirdefinirdefinirdefinir variáveisvariáveisvariáveisvariáveis com o com o com o com o mesmomesmomesmomesmo nomenomenomenome emememem escoposescoposescoposescopos diferentesdiferentesdiferentesdiferentes.... ConsidereConsidereConsidereConsidere esteesteesteeste um CONTRAum CONTRAum CONTRAum CONTRA---- EXEMPLOEXEMPLOEXEMPLOEXEMPLO!!!! } void exemplo3() { printf("\t%2d %2d\n", i++, j--); } int main (void) { int j = 20; exemplo1(); printf("\t%2d %2d\n", i++, j--); exemplo1(); exemplo2(); exemplo2(); exemplo2(); exemplo3(); exemplo1(); printf("\t%2d %2d\n", i++, j--); return 0; } exemplo: escopo de variáveis #include <stdio.h> int i = 10; static int j = 10; void exemplo1() { int i = 5; int j = 15; printf("\t%2d %2d\n", i++, j--); } void exemplo2() { static int i = 1; printf("\t%2d %2d\n", i++, j--); }} void exemplo3() { printf("\t%2d %2d\n", i++, j--); } int main (void) { int j = 20; exemplo1(); printf("\t%2d %2d\n", i++, j--); exemplo1(); exemplo2(); exemplo2(); exemplo2(); exemplo3(); exemplo1(); printf("\t%2d %2d\n", i++, j--); return 0; } (uso esquemático da memória por diferentes memória por diferentes tipos de variáveis) 53 código do programa … variáveis globais e estáticas (global) i 10 (static) j 10 memória alocada dinamicamente — — uso esquemático da memória #include <stdio.h> int i=10; static int j=10; void exemplo1() { int i = 5; int j = 15; printf("\t%2d %2d\n", i++, j--); } void exemplo2() { static int i=1; printf("\t%2d %2d\n", i++, j--); } memória livre pilha 54 } void exemplo3() { printf("\t%2d %2d\n", i++, j--); } int main (void) { int j = 20; exemplo1(); printf("\t%2d %2d\n", i++, j--); exemplo1(); exemplo2(); exemplo2(); exemplo2(); exemplo3(); exemplo1(); printf("\t%2d %2d\n", i++, j--); return 0; } uso esquemático da memória código do programa … variáveis globais e estáticas (global) i 10 (static) j 10 memória alocada dinamicamente — — #include <stdio.h> int i=10; static int j=10; void exemplo1() { int i = 5; int j = 15; printf("\t%2d %2d\n", i++, j--); } void exemplo2() { static int i=1; printf("\t%2d %2d\n", i++, j--); } 55 memória livre pilha main j 20 } void exemplo3() { printf("\t%2d %2d\n", i++, j--); } int main (void) { int j = 20; exemplo1(); printf("\t%2d %2d\n", i++, j--); exemplo1(); exemplo2(); exemplo2(); exemplo2(); exemplo3(); exemplo1(); printf("\t%2d %2d\n", i++, j--); return 0; } uso esquemático da memória #include <stdio.h> int i=10; static int j=10; void exemplo1() { int i = 5; int j = 15; printf("\t%2d %2d\n", i++, j--); } void exemplo2() { static int i=1; printf("\t%2d %2d\n", i++, j--); } (global) i 10 (global) i 10 (static) j 10 (static) j 10 Ao entrar em exemplo1, empilha i e j locais 56 } void exemplo3() { printf("\t%2d %2d\n", i++, j--); } int main (void) { int j = 20; exemplo1(); printf("\t%2d %2d\n", i++, j--); exemplo1(); exemplo2(); exemplo2(); exemplo2(); exemplo3(); exemplo1(); printf("\t%2d %2d\n", i++, j--); return 0; } exemplo1 j 15 i 5 main j 20 main j 20 uso esquemático da memória (global) i 10 (global) i 10 (static) j 10 (static) j 10 #include <stdio.h> int i=10; static int j=10; void exemplo1() { int i = 5; int j = 15; printf("\t%2d %2d\n", i++, j--); } void exemplo2() { static int i=1; printf("\t%2d %2d\n", i++, j--); } Após imprimir valores, incrementa i (local) e decrementa j (local). 57 exemplo1 j 15 exemplo1 j 14 i 5 2 i 6 main j 20 main j 20 } void exemplo3() { printf("\t%2d %2d\n", i++, j--); } int main (void) { int j = 20; exemplo1(); printf("\t%2d %2d\n", i++, j--); exemplo1(); exemplo2(); exemplo2(); exemplo2(); exemplo3(); exemplo1(); printf("\t%2d %2d\n", i++, j--); return 0; } 5 15 2 1 3 uso esquemático da memória #include <stdio.h> int i=10; static int j=10; void exemplo1() { int i = 5; int j = 15; printf("\t%2d %2d\n", i++, j--); } void exemplo2() { static int i=1; printf("\t%2d %2d\n", i++, j--); } (global) i 10 (global) i 10 (static) j 10 (static) j 10 Ao sair de exemplo1, desempilha i e j locais. 58 } void exemplo3() { printf("\t%2d %2d\n", i++, j--); } int main (void) { int j = 20; exemplo1(); printf("\t%2d %2d\n", i++, j--); exemplo1(); exemplo2(); exemplo2(); exemplo2(); exemplo3(); exemplo1(); printf("\t%2d %2d\n", i++, j--); return 0; } 5 15 exemplo1 j 14 i 6 main j 20 main j 20 uso esquemático da memória #include <stdio.h> int i=10; static int j=10; void exemplo1() { int i = 5; int j = 15; printf("\t%2d %2d\n", i++, j--); } void exemplo2() { static int i=1; printf("\t%2d %2d\n", i++, j--); } (global) i 10 (global) i 11 (static) j 10 (static) j 10 2 Após imprimir valores, incrementa i (global) e decrementa j (local à função main). 59 } void exemplo3() { printf("\t%2d %2d\n", i++, j--); } int main (void) { int j = 20; exemplo1(); printf("\t%2d %2d\n", i++, j--); exemplo1(); exemplo2(); exemplo2(); exemplo2(); exemplo3(); exemplo1(); printf("\t%2d %2d\n", i++, j--); return 0; } 5 15 10 20 main j 20 main j 193 1 uso esquemático da memória #include <stdio.h> int i=10; static int j=10; void exemplo1() { int i = 5; int j = 15; printf("\t%2d %2d\n", i++, j--); } void exemplo2() { static int i=1; printf("\t%2d %2d\n", i++, j--); } (global) i 11 (global) i 11 (static) j 10 (static) j 10 Ao entrar em exemplo1, empilha i e j locais 60 } void exemplo3() { printf("\t%2d %2d\n", i++, j--); } int main (void) { int j = 20; exemplo1(); printf("\t%2d %2d\n", i++, j--);exemplo1(); exemplo2(); exemplo2(); exemplo2(); exemplo3(); exemplo1(); printf("\t%2d %2d\n", i++, j--); return 0; } 5 15 10 20 exemplo1 j 15 i 5 main j 19 main j 19 uso esquemático da memória #include <stdio.h> int i=10; static int j=10; void exemplo1() { int i = 5; int j = 15; printf("\t%2d %2d\n", i++, j--); } void exemplo2() { static int i=1; printf("\t%2d %2d\n", i++, j--); } (global) i 11 (global) i 11 (static) j 10 (static) j 10 Após imprimir valores, incrementa i (local) e decrementa j (local). 61 } void exemplo3() { printf("\t%2d %2d\n", i++, j--); } int main (void) { int j = 20; exemplo1(); printf("\t%2d %2d\n", i++, j--); exemplo1(); exemplo2(); exemplo2(); exemplo2(); exemplo3(); exemplo1(); printf("\t%2d %2d\n", i++, j--); return 0; } 5 15 10 20 5 15 exemplo1 j 15 exemplo1 j 14 i 5 i 6 main j 19 main j 19 3 1 2 uso esquemático da memória #include <stdio.h> int i=10; static int j=10; void exemplo1() { int i = 5; int j = 15; printf("\t%2d %2d\n", i++, j--); } void exemplo2() { static int i=1; printf("\t%2d %2d\n", i++, j--); } (global) i 11 (global) i 11 (static) j 10 (static) j 10 Ao sair de exemplo1, desempilha i e j locais. 62 } void exemplo3() { printf("\t%2d %2d\n", i++, j--); } int main (void) { int j = 20; exemplo1(); printf("\t%2d %2d\n", i++, j--); exemplo1(); exemplo2(); exemplo2(); exemplo2(); exemplo3(); exemplo1(); printf("\t%2d %2d\n", i++, j--); return 0; } 5 15 10 20 5 15 exemplo1 j 14 i 6 main j 19 main j 19 uso esquemático da memória #include <stdio.h> int i=10; static int j=10; void exemplo1() { int i = 5; int j = 15; printf("\t%2d %2d\n", i++, j--); } void exemplo2() { static int i=1; printf("\t%2d %2d\n", i++, j--); } (global) i 11 (global) i 11 (static) j 10 (static) j 10 exemplo2 i 1 Ao entrar em exemplo2, empilha i estática local à função exemplo2. 63 } void exemplo3() { printf("\t%2d %2d\n", i++, j--); } int main (void) { int j = 20; exemplo1(); printf("\t%2d %2d\n", i++, j--); exemplo1(); exemplo2(); exemplo2(); exemplo2(); exemplo3(); exemplo1(); printf("\t%2d %2d\n", i++, j--); return 0; } 5 15 10 20 5 15 main j 19 main j 19 uso esquemático da memória #include <stdio.h> int i=10; static int j=10; void exemplo1() { int i = 5; int j = 15; printf("\t%2d %2d\n", i++, j--); } void exemplo2() { static int i=1; printf("\t%2d %2d\n", i++, j--); } (global) i 11 (global) i 11 (static) j 10 (static) j 9 exemplo2 i 1 exemplo2 i 22 3 Após imprimir valores, incrementa i (estática local à função exemplo2) e decrementa j (estática do módulo). 64 } void exemplo3() { printf("\t%2d %2d\n", i++, j--); } int main (void) { int j = 20; exemplo1(); printf("\t%2d %2d\n", i++, j--); exemplo1(); exemplo2(); exemplo2(); exemplo2(); exemplo3(); exemplo1(); printf("\t%2d %2d\n", i++, j--); return 0; } 5 15 10 20 5 15 1 10 main j 19 main j 19 1 uso esquemático da memória #include <stdio.h> int i=10; static int j=10; void exemplo1() { int i = 5; int j = 15; printf("\t%2d %2d\n", i++, j--); } void exemplo2() { static int i=1; printf("\t%2d %2d\n", i++, j--); } (global) i 11 (global) i 11 (static) j 9 (static) j 9 exemplo2 i 2 exemplo2 i 2 Ao sair de exemplo2, não desempilha i estática local à função exemplo2. 65 } void exemplo3() { printf("\t%2d %2d\n", i++, j--); } int main (void) { int j = 20; exemplo1(); printf("\t%2d %2d\n", i++, j--); exemplo1(); exemplo2(); exemplo2(); exemplo2(); exemplo3(); exemplo1(); printf("\t%2d %2d\n", i++, j--); return 0; } 5 15 10 20 5 15 1 10 main j 19 main j 19 uso esquemático da memória #include <stdio.h> int i=10; static int j=10; void exemplo1() { int i = 5; int j = 15; printf("\t%2d %2d\n", i++, j--); } void exemplo2() { static int i=1; printf("\t%2d %2d\n", i++, j--); } (global) i 11 (global) i 11 (static) j 9 (static) j 8 exemplo2 i 2 exemplo2 i 32 3 Após imprimir valores, incrementa i (estática local à função exemplo2) e decrementa j (estática do módulo). 66 } void exemplo3() { printf("\t%2d %2d\n", i++, j--); } int main (void) { int j = 20; exemplo1(); printf("\t%2d %2d\n", i++, j--); exemplo1(); exemplo2(); exemplo2(); exemplo2(); exemplo3(); exemplo1(); printf("\t%2d %2d\n", i++, j--); return 0; } 5 15 10 20 5 15 1 10 2 9 main j 19 main j 19 1 uso esquemático da memória #include <stdio.h> int i=10; static int j=10; void exemplo1() { int i = 5; int j = 15; printf("\t%2d %2d\n", i++, j--); } void exemplo2() { static int i=1; printf("\t%2d %2d\n", i++, j--); } (global) i 11 (global) i 11 (static) j 9 (static) j 8 exemplo2 i 2 exemplo2 i 3 Ao sair de exemplo2, não desempilha i estática local à função exemplo2. 67 } void exemplo3() { printf("\t%2d %2d\n", i++, j--); } int main (void) { int j = 20; exemplo1(); printf("\t%2d %2d\n", i++, j--); exemplo1(); exemplo2(); exemplo2(); exemplo2(); exemplo3(); exemplo1(); printf("\t%2d %2d\n", i++, j--); return 0; } 5 15 10 20 5 15 1 10 2 9 main j 19 main j 19 uso esquemático da memória #include <stdio.h> int i=10; static int j=10; void exemplo1() { int i = 5; int j = 15; printf("\t%2d %2d\n", i++, j--); } void exemplo2() { static int i=1; printf("\t%2d %2d\n", i++, j--); } (global) i 11 (global) i 11 (static) j 8 (static) j 7 exemplo2 i 3 exemplo2 i 42 3 Após imprimir valores, incrementa i (estática local à função exemplo2) e decrementa j (estática do módulo). 68 } void exemplo3() { printf("\t%2d %2d\n", i++, j--); } int main (void) { int j = 20; exemplo1(); printf("\t%2d %2d\n", i++, j--); exemplo1(); exemplo2(); exemplo2(); exemplo2(); exemplo3(); exemplo1(); printf("\t%2d %2d\n", i++, j--); return 0; } 5 15 10 20 5 15 1 10 2 9 3 8 main j 19 main j 19 1 uso esquemático da memória #include <stdio.h> int i=10; static int j=10; void exemplo1() { int i = 5; int j = 15; printf("\t%2d %2d\n", i++, j--); } void exemplo2() { static int i=1; printf("\t%2d %2d\n", i++, j--); } (global) i 11 (global) i 11 (static) j 7 (static) j 7 exemplo2 i 4 exemplo2 i 4 Ao sair de exemplo2, não desempilha i estática local à função exemplo2. 69 } void exemplo3() { printf("\t%2d %2d\n", i++, j--); } int main (void) { int j = 20; exemplo1(); printf("\t%2d %2d\n", i++, j--); exemplo1(); exemplo2(); exemplo2(); exemplo2(); exemplo3(); exemplo1(); printf("\t%2d %2d\n", i++, j--); return 0; } 5 15 10 20 5 15 1 10 2 9 3 8 main j 19 main j 19 uso esquemático da memória #include <stdio.h> int i=10; static int j=10; void exemplo1() { int i = 5; int j = 15; printf("\t%2d %2d\n", i++, j--); } void exemplo2() { static int i=1; printf("\t%2d %2d\n", i++, j--); } (global) i 11 (global) i 12 (static) j 7 (static) j 6 exemplo2 i 4 exemplo2 i 4 2 3 Após imprimir valores, incrementa i(global) e decrementa j (estática do módulo). 70 } void exemplo3() { printf("\t%2d %2d\n", i++, j--); } int main (void) { int j = 20; exemplo1(); printf("\t%2d %2d\n", i++, j--); exemplo1(); exemplo2(); exemplo2(); exemplo2(); exemplo3(); exemplo1(); printf("\t%2d %2d\n", i++, j--); return 0; } 5 15 10 20 5 15 1 10 2 9 3 8 11 7 main j 19 main j 19 1 uso esquemático da memória #include <stdio.h> int i=10; static int j=10; void exemplo1() { int i = 5; int j = 15; printf("\t%2d %2d\n", i++, j--); } void exemplo2() { static int i=1; printf("\t%2d %2d\n", i++, j--); } (global) i 12 (global) i 12 (static) j 6 (static) j 6 exemplo2 i 4 exemplo2 i 4 3 Ao sair de exemplo3, não há o que desempilhar. 71 } void exemplo3() { printf("\t%2d %2d\n", i++, j--); } int main (void) { int j = 20; exemplo1(); printf("\t%2d %2d\n", i++, j--); exemplo1(); exemplo2(); exemplo2(); exemplo2(); exemplo3(); exemplo1(); printf("\t%2d %2d\n", i++, j--); return 0; } 5 15 10 20 5 15 1 10 2 9 3 8 11 7 main j 19 main j 19 uso esquemático da memória #include <stdio.h> int i=10; static int j=10; void exemplo1() { int i = 5; int j = 15; printf("\t%2d %2d\n", i++, j--); } void exemplo2() { static int i=1; printf("\t%2d %2d\n", i++, j--); } (global) i 12 (global) i 12 (static) j 6 (static) j 6 exemplo2 i 4 exemplo2 i 4 Ao entrar em exemplo1, empilha i e j locais 72 } void exemplo3() { printf("\t%2d %2d\n", i++, j--); } int main (void) { int j = 20; exemplo1(); printf("\t%2d %2d\n", i++, j--); exemplo1(); exemplo2(); exemplo2(); exemplo2(); exemplo3(); exemplo1(); printf("\t%2d %2d\n", i++, j--); return 0; } 5 15 10 20 5 15 1 10 2 9 3 8 11 7 exemplo1 j 15 i 5 main j 19 main j 19 uso esquemático da memória #include <stdio.h> int i=10; static int j=10; void exemplo1() { int i = 5; int j = 15; printf("\t%2d %2d\n", i++, j--); } void exemplo2() { static int i=1; printf("\t%2d %2d\n", i++, j--); } (global) i 12 (global) i 12 (static) j 6 (static) j 6 exemplo2 i 4 exemplo2 i 4 Após imprimir valores, incrementa i (local) e decrementa j (local). 73 } void exemplo3() { printf("\t%2d %2d\n", i++, j--); } int main (void) { int j = 20; exemplo1(); printf("\t%2d %2d\n", i++, j--); exemplo1(); exemplo2(); exemplo2(); exemplo2(); exemplo3(); exemplo1(); printf("\t%2d %2d\n", i++, j--); return 0; } 5 15 10 20 5 15 1 10 2 9 3 8 11 7 15 5 exemplo1 j 15 exemplo1 j 14 i 5 i 6 main j 19 main j 19 3 1 2 uso esquemático da memória #include <stdio.h> int i=10; static int j=10; void exemplo1() { int i = 5; int j = 15; printf("\t%2d %2d\n", i++, j--); } void exemplo2() { static int i=1; printf("\t%2d %2d\n", i++, j--); } (global) i 12 (global) i 12 (static) j 6 (static) j 6 exemplo2 i 4 exemplo2 i 4 Ao sair de exemplo1, desempilha i e j locais. 74 } void exemplo3() { printf("\t%2d %2d\n", i++, j--); } int main (void) { int j = 20; exemplo1(); printf("\t%2d %2d\n", i++, j--); exemplo1(); exemplo2(); exemplo2(); exemplo2(); exemplo3(); exemplo1(); printf("\t%2d %2d\n", i++, j--); return 0; } 5 15 10 20 5 15 1 10 2 9 3 8 11 7 15 5 exemplo1 j 14 i 6 main j 19 main j 19 uso esquemático da memória #include <stdio.h> int i=10; static int j=10; void exemplo1() { int i = 5; int j = 15; printf("\t%2d %2d\n", i++, j--); } void exemplo2() { static int i=1; printf("\t%2d %2d\n", i++, j--); } (global) i 12 (global) i 13 (static) j 6 (static) j 5 exemplo2 i 4 exemplo2 i 4 2 3 Após imprimir valores, incrementa i (global) e decrementa j (local à main). 75 } void exemplo3() { printf("\t%2d %2d\n", i++, j--); } int main (void) { int j = 20; exemplo1(); printf("\t%2d %2d\n", i++, j--); exemplo1(); exemplo2(); exemplo2(); exemplo2(); exemplo3(); exemplo1(); printf("\t%2d %2d\n", i++, j--); return 0; } 5 15 10 20 5 15 1 10 2 9 3 8 11 7 15 5 12 6 main j 19 main j 19 1 uso esquemático da memória #include <stdio.h> int i=10; static int j=10; void exemplo1() { int i = 5; int j = 15; printf("\t%2d %2d\n", i++, j--); } void exemplo2() { static int i=1; printf("\t%2d %2d\n", i++, j--); } (global) i 13 (static) j 5 exemplo2 i 4 2 Ao sair do programa, libera espaço de todas as variáveis. 76 } void exemplo3() { printf("\t%2d %2d\n", i++, j--); } int main (void) { int j = 20; exemplo1(); printf("\t%2d %2d\n", i++, j--); exemplo1(); exemplo2(); exemplo2(); exemplo2(); exemplo3(); exemplo1(); printf("\t%2d %2d\n", i++, j--); return 0; } 5 15 10 20 5 15 1 10 2 9 3 8 11 7 15 5 12 6 main j 19 1 dúvidas?dúvidas? 77 Prof. Gustavo Moreira gmoreira@inf.puc-rio.br 04_07_escopo_var.c 1 módulo var val 2 módulo var val 3 módulo var val 4 módulo var val 5 módulo var val 6 módulo var val 7 módulo var val 8 módulo var val 78 9 módulo var val 10 módulo var val 11 módulo var val 12 módulo var val 13 módulo var val 14 módulo var val 15 módulo var val 16 módulo var val 79
Compartilhar