Subalgoritmos II

Last updated: September 30th, 2018

Introdução

Vimos na aula anterior o que são e como funcionam as funções na linguagem C. Hoje iremos aprender mais sobre os parâmetros de uma função.

Os parâmetros de uma função são valores externos que são passados para a função utilizar como variável local em seu escopo. Os parâmetros são de duas categorias: valor e referência.

Parâmetros de função

Parâmetros por Valor

Parâmetros por valor são a maneira default de se passar argumentos para uma função. Nesta categoria de parâmetro, é feita uma cópia da variável a ser passada para a função. Ou seja, a função não altera valores das variáveis externas, somente das variáveis internas (locais).

Logo, um parâmetro por valor pode ser tanto uma variável quanto uma constante.

Para definir que um parâmetro seja por valor, basta colocar o tipo daquele parâmetro como o tipo desejado.

void parametro_valor(int a, float b, char c){...}
  • O parâmetro a é um parâmetro por valor do tipo int
  • O parâmetro b é um parâmetro por valor do tipo float
  • O parâmetro c é um parâmetro por valor do tipo char

Exemplo

Lembre-se de que os parâmetros por valor não alteram o valor da variável fora da função, observe.

#include < stdio.h >

void param_valor(int x){
    x += 2;
    printf("Dentro da funcao: %d\n", x);
}

int main(){
    int x = 2;
    printf("Antes da funcao: %d\n", x);
    param_valor(x);
    printf("Fora da funcao: %d\n", x);
    
    return 0;
}
                                
Code Execution

Exemplo

O programa a seguir lê um número n e em seguida lê n números, informando se o mesmo é par e maior que 20, par e menor ou igual a 20 ou impar.

#include < stdio.h >

int check(int x){
    if(x%2 == 0){
        if(x > 20)
            return 1;
        return 0;
    }
    return -1;
}

int main(){

    int n,i,y, resp;
    scanf("%d", &n);
    for(i = 0; i < n; i++){
        scanf("%d", &y);
        resp = check(y);
        if(resp == 1)
            printf("%d eh par e maior que 20\n",y);
        else if(resp == 0)
            printf("%d eh par e menor ou igual a 20\n",y);
        else
            printf("%d eh impar\n",y);
    }

    return 0;
}
Download Code

Exemplo no Terminal

APC$ gcc -o valor -std=c11 valor.c
APC$ ./valor
4
1
1 eh impar
20
20 eh par e menor ou igual a 20
25
25 eh impar
26
26 eh par e maior que 20

Parâmetros por Referência

Os parâmetros por referência não são uma cópia do argumento a ser passado, mas uma referência para este. Ou seja, parâmetros por referência na verdade são ponteiros para as variáveis passadas.

Logo, eles só podem ser usados com variáveis.

Para definir que um parâmetro seja por valor, deve-se colocar o tipo daquele parâmetro como um ponteiro para o tipo desejado.

void parametro_referência(int* a, float* b, char* c){...}
  • O parâmetro a é um parâmetro por referência do tipo ponteiro para int
  • O parâmetro b é um parâmetro por referência do tipo ponteiro para float
  • O parâmetro c é um parâmetro por referência do tipo ponteiro para char

Exemplo

Lembre-se de que funções com parâmetros por referência alteram as variáveis externas à função. Observe.

#include < stdio.h >

/* Lembre-se que operacoes com ponteiros sao um pouco diferentes. */
void param_ref(int* x){
    *x += 2;
    printf("Dentro da funcao: %d\n", *x);
}

int main(){
    int x = 2;
    printf("Antes da funcao: %d\n", x);
    param_ref(&x);
    printf("Fora da funcao: %d\n", x);
    
    return 0;
}
                                
Code Execution

Exemplo

O programa a seguir realiza o mesmo papel do programa anterior porém a diferença é que há uma passagam de valor por referência



#include < stdio.h >

/* Note que esta função é do tipo void, enquanto a mesma função com parâmetro de valor
   precisava ser do tipo int */
void check(int x, int *resp){
    if(x%2 == 0){
        if(x > 20)
            *resp = 1;
        else 
            *resp = 0;
    }
    else
        *resp = - 1;
}

int main(){

    int n,i,y, resp;
    scanf("%d", &n);
    for(i = 0; i < n; i++){
        scanf("%d", &y);
        check(y, &resp);
        if(resp == 1)
            printf("%d eh par e maior que 20\n",y);
        else if(resp == 0)
            printf("%d eh par e menor ou igual a 20\n",y);
        else
            printf("%d eh impar\n",y);
    }

    return 0;
}
Download Code

Exemplo no Terminal

APC$ gcc -o referencia -std=c11 referencia.c
APC$ ./referencia
4
1
1 eh impar
20
20 eh par e menor ou igual a 20
25
25 eh impar
26
26 eh par e maior que 20

Exercícios Recomendados

Materiais Extras

Múltiplos Retornos

Uma funçao em C só pode retornar 1 valor, de qualquer tipo. Existem algumas maneiras de conseguir "retornar" mais de um valor no entanto, e uma delas é com ponteiros.

Podemos tomar vantagem do fato que parâmetros por referência, em uma função, referenciam uma variável externa à função e utilizar esses ponteiros para alterar o valor destas variáveis dentro da função. Desta forma, ao final da execução da função o valor destas variáveis terá sido alterado, fazendo parecer que a função "retornou" esses valores também.

Este não é um uso tão comum, no entanto, pois causa efeitos colaterais que podem ser difíceis de detectar, uma vez que este "retorno" não é explícito.

Exemplo

#include <stdio.h>
#include <math.h>

/* Esta função retorna o valor de delta de uma função quadratica.
   Se a função tiver raízes reais, elas também são "retornadas".
Parâmetros por valor: a, b, c. As constantes reais da função.
Parâmetros por referência: x1 and x2. Referência para as variáveis onde
as raízes devem ser armazenadas, se existirem. */
double baskara(double a, double b, double c, double* x1, double* x2){
    double delta = b*b - 4*a*c;
    if (delta > 0){
        /* Assigns solutions of function, if they exist */
        *x1 = (-b + sqrt(delta))/(2*a);
        *x2 = (-b - sqrt(delta))/(2*a);
    }
    return delta;
}

int main(){
    double a,b,c,x1,x2;
    printf("Função com raizes reais\n");
    a = 1;
    b = -3;
    c = 1;
    x1 = 0;
    x2 = 0;
    /* Note que x1 e x2 são parâmetros de referência */
    double delta = baskara(a, b, c, &x1, &x2);
    printf("Delta: %.2lf\n", delta);
    /* Note que o valor de x1 e x2 nao eh mais 0 */
    printf("X1: %.2lf\nX2: %.2lf\n", x1, x2);
    printf("===============\n");
    printf("Função sem raizes reais\n");
    a = 1;
    b = 3;
    c = 3;
    x1 = 0;
    x2 = 0;
    delta = baskara(a, b, c, &x1, &x2);
    printf("Delta: %.2lf\n", delta);
    /* Note que o valor de x1 e x2 ainda eh 0 */
    printf("X1: %.2lf\nX2: %.2lf\n", x1, x2);
    
    return 0;
}
                                        
Download Code

Output

Executando o código acima temos a seguinte saída abaixo. Note que não aletamos o valor de x1 e x2 na função main para a função com raízes reais. Esses valores foram alterados pela função baskara.

Obs: Note que na linha de compilação foi usada a flag -lm. Ela é necessária para utilizar funções da biblioteca math.h. A função sqrt é desta biblioteca.

APC$ gcc -lm -o baskara -std=c11 baskara.c
APC$ ./baskara
Função com raizes reais
Delta: 5.00
X1: 2.62
X2: 0.38
===============
Função sem raizes reais
Delta: -3.00
X1: 0.00
X2: 0.00