Analise o seguinte programa:
void func1 (int x) {
x = 9 * x;
}
void func2 (int v[]) {
v[0] = 9 * v[0] ;
}
int main (void) {
int x, v[2];
x = 111;
func1 (x); printf ("x: %d\n", x);
v[0] = 111;
func2 (v); printf ("v[0]: %d\n", v[0]);
return EXIT_SUCCESS;
}
E responda por que o programa produz a seguinte resposta:
x:
void func1 (int x) {
x = 9 * x;
}
void func2 (int v[]) {
v[0] = 9 * v[0] ;
}
int main (void) {
int x, v[2];
x = 111;
func1 (x); printf ("x: %d\n", x);
v[0] = 111;
func2 (v); printf ("v[0]: %d\n", v[0]);
return EXIT_SUCCESS;
}
x:
Passo 1
O enunciado dá o código em C e mostra a saída obtida:
- O programa imprime primeiro
x: 111e depoisv[0]: 999. - As atribuições antes das chamadas são:
e .
A pergunta implícita é: por que após as chamadas de função a variávelficou com valor enquanto ficou com valor ?
Passo 2
Entender exatamente o que cada função recebe quando é chamada.
- Em
func1(int x)o parâmetroxé do tipo inteiro simples. Quandofunc1(x)é chamada, o que se passa para a função é uma cópia do valor dex. Ou seja, dentro defunc1existe uma variável local (também chamadax) que começou com uma cópia do valor. - Em
func2(int v[])o parâmetro escrito comoint v[]é, na verdade, sintaticamente equivalente aint *vem C. Portanto, quandofunc2(v)é chamada, o que se passa para a função é um ponteiro (um endereço) que aponta para o primeiro elemento do arrayvdomain.
Passo 3
Explicar o conceito central: passagem por valor em C.
- Em C, todos os parâmetros são passados por valor. Isso significa que a função recebe uma cópia do que foi passado.
- Se o que é copiado é um inteiro (como em
func1), a função manipula só essa cópia; a variável original nomainnão muda. - Se o que é copiado é um ponteiro (como em
func2, porque o nome do array decai para um ponteiro), a cópia é do endereço. Ambas — a cópia (no corpo da função) e o valor original (nomain) — apontam para a mesma área de memória. Assim, operações que usam esse ponteiro para modificar a memória afetam o conteúdo domain.
Passo 4
Aplicar isso ao caso de
func1.- Antes da chamada: no
main,. - Chamada
func1(x): a função recebe uma cópia do valorem seu próprio parâmetro local x. - Dentro de
func1executa-sex = 9 * x;— isto altera só a cópia local para. - Ao retornar, essa variável local deixa de existir; o
do mainnão foi modificado e permanece. - Por isso o
printflogo depois imprimex: 111.
Passo 5
Aplicar isso ao caso de
func2.- Antes da chamada: no
main,. - Chamada
func2(v): o nomevdecai para o endereço de seu primeiro elemento; a função recebe uma cópia desse endereço (um ponteiro parav[0]). - Dentro de
func2a expressãov[0] = 9 * v[0];faz desreferência do ponteiro e escreve diretamente no local de memória ondev[0]domainestá armazenado. Ou seja, altera o conteúdo do array domain. - Depois do retorno, o
mainvêv[0]modificado para. - Por isso o
printfimprimev[0]: 999.
Passo 6
Resumo visual (conceitual) rápido:
- Para
func1(x):maintem. func1recebe cópia: localx = 111→ multiplica → localx = 999→ retorna →main.xpermanece.
- Para
func2(v):maintemv[0] = 111.func2recebe ponteiro parav[0]→ escreve através do ponteiro →v[0]emmainfica.
Passo 7
Observações finais e dica prática para a prova (estilo “truque” para lembrar):
- Em C, se quiser que uma função modifique um inteiro do chamador, passe o endereço:
void func1(int *px) { *px = 9 * (*px); }e chamefunc1(&x);. - Arrays nunca são passados “por cópia” em C; o que se passa é um ponteiro para seu primeiro elemento (logo, funções podem modificar elementos do array).
Resposta
Porque em C os parâmetros são passados por valor: em , então a multiplicação altera só a cópia local (o
do ). Já em .
func1(int x) é recebida apenas uma cópia do inteiro
main continua
func2(int v[]) o parâmetro é, na prática, um ponteiro para o primeiro elemento do array (equivalente a int *v), portanto a atribuição v[0] = 9 * v[0] modifica diretamente a memória do array do main, tornando v[0] igual a