Passando por referência em C ou C++

Uma dúvida que costuma aparecer em quem está aprendendo C é por que algumas funções necessitam que seus argumentos possuam ‘&’ na frente para funcionar como deveriam. O nome disso é ‘passar por referência’ e difere de ‘passar por cópia’ por permitir que a função altere o valor da variável.

Digamos que por um motivo qualquer, você precisa de uma função que pegue o valor da variável e some 10. Dependendo de como você irá usá-la, há três maneiras diferentes de se fazer isso (quatro em C++).

A primeira forma passa o valor da variável por cópia e não retorna nenhum valor, apenas imprime na tela o resultado:

void soma_por_copia_um( int x ) 
{ 
    x = x + 10; 
    printf( "%d ", x); 
}

No main do programa, haverá uma parte com um código parecido com isso:

int z = 20; 
soma_por_copia_um( z ); 
printf( "%d ", z );

Nesse código, o valor da variável z é passado para a função soma_por_copia_um() e copiado para a variável x. Então a essa variável é somado 10, mas z continua intocada. Isso explica o resultado que obtivemos: 30 20.

Mas e se quisessemos que o valor de z fosse permanentemente alterado? Existem duas maneiras de se fazer isso, três se você considerar um açucar sintático existente no C++ não tão útil assim.

A primeira é justamente passar o valor por referência. O código a cima sofre apenas duas alterações: aparece um * na definição da função e um & quando formos chamá-la:

void soma_por_ref_um( int *x ) 
{ 
    x = x + 10; 
    printf( "%d ", x); 
}

E no main do programa, um código parecido com isso:

int z = 20; 
soma_por_ref_um( &z ); 
printf( "%d ", z );

Aqui acontece algo um pouco diferente. Se você lembra dos ponteiros, entenderá rapidamente o que está acontecendo. A função soma_por_ref_um() aceita como argumento um ponteiro para um inteiro. Quando chamamos a função, passamos o endereço de z com o operador &, portanto, nesse caso x não possui um valor copiado de z, mas aponta para z. Qualquer alteração feita a x alterará o valor de z. Por isso quando rodamos esse segundo exemplo, temos 30 30.

Outra maneira é usar uma função que não retorne void. Esse método possui algumas vantagens, como alterar o valor apenas se você quiser e passar a função como argumento para outra.

int soma_por_copia_dois( int x ) 
{ 
    x = x + 10; 
    printf( "%d ", x);
    return x;
}

No main agora teremos um código um pouco maior:

int z = 20; 
soma_por_copia_dois( z ); 
printf( "%d ", z );
z = soma_por_copia_dois( z );
printf( "%d ", z );
printf( "%d ", soma_por_copia_dois( z ) );

Declaramos a variável z com valor 20 e passamos para a função por cópia. Ela irá imprimir 30, mas z continua valendo 20. Então mandamos que o valor de z seja o valor retornado pela função. Ela irá imprimir 30 e z passou a valer 30 também. Depois passamos a função como argumento para o próximo printf, que imprime 40, mas z continua valendo 30. Essa é de longe a maneira mais versátil de se fazer o que queríamos.

A última forma, presente apenas no C++ é a mesma coisa que passar por referência normalmente, mas na declaração da função teremos & no lugar de *, e quando chamarmos a função, colocaremos apenas a variável.

void soma_por_ref_dois( int &x );
soma_por_ref_dois( z );

O problema de se utilizar esse modo de referência é que não saberemos, quando estivermos chamando a função, se ela está copiando o valor ou alterando-o.

Publicidade

5 Respostas para “Passando por referência em C ou C++

  1. Rafael sandrini novembro 23, 2009 às 9:57 pm

    Mt bem, estava estudando e ajudou bastante!

  2. Guilherme Carlos setembro 18, 2010 às 9:17 pm

    Muito bom! Estava precisando disso, dei uma procurada e sua página apareceu logo no começo. Explicou muito bem!

  3. Luis Fernando janeiro 3, 2012 às 4:35 pm

    Agradeço a ajuda que deu; Estava precisando relembrar algumas coisas e o conteúdo ai, me ajudou antes de que fosse para uma pilha de livros para tirar uma dúvida. :)

  4. Cézanne agosto 21, 2013 às 11:47 am

    Tirou a dúvida que eu tinha, vi uma declaração de variável com & e não sabia deste recurso, já que até agora só conheço C, C++ ainda não. Mas achei umas coisas estranhas:
    -No 3º bloco vc soma 10 ao ponteiro x. Isso seria mais um “açúcar sintático do c++? Em c isso mudaria o endereço do ponteiro que passaria a apontar pra um local desconhecido.
    -No 6º bloco vc disse que o primeiro printf iria imprimir 30 e z continuaria a valer 20. Realmente z não será alterado mas o primeiro printf resultará 20 tbm.
    Vlw

  5. Jan Palach maio 20, 2014 às 12:43 pm

    “void soma_por_ref_um( int *x )
    {
    x = x + 10;
    printf( “%d “, x);
    }”

    A linha x = x + 10 não deveria ser *x = *x + 10?

    APenas usando X você está modificando o endereço e não o conteúdo.

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s

%d blogueiros gostam disto: