revisão sobre ponteiros em c

29
Tutoria AEDSI Pablo Silva

Upload: pablo-silva

Post on 20-Jul-2015

68 views

Category:

Education


3 download

TRANSCRIPT

Page 1: Revisão sobre ponteiros em C

Tutoria AEDSIPablo Silva

Page 2: Revisão sobre ponteiros em C

Revisão

Nesta revisão, iremos relembrar os conceitos importantes de ponteiros e aplicá-los para entender o que é passagem de parâmetros por referência para uma função e como ela se diferencia da passagem por valor.

Page 3: Revisão sobre ponteiros em C

Ponteiros?

- Ponteiros são tipos de variáveis que recebem endereços.

- Esses endereços são os lugares da memória onde estão armazenados valores de variáveis.

- O nome ponteiro é uma analogia, referindo que esse tipo de variável “aponta”para um endereço de memória.

Page 4: Revisão sobre ponteiros em C

Estrutura de um ponteiro

int * pont;

Tipo do ponteiro: como dito o ponteiro é uma variável, logo precisa de um tipo. Este tipo, indica o tipo de valor que está armazendo no endereço associado com este ponteiro, ou em outras palavras, qual o tipo de dado que o espaço de memória aceita.

Operador asterisco: o que diferencia ponteiros das outras variáveis é o operador asterisco.

Nome do ponteiro: segue as mesmas regras de nomeação de variáveis.

Page 5: Revisão sobre ponteiros em C

Usando um ponteiroVamos ver como é a estrutura de uma função

int main() {

int a = 10;int* p = &a;

return 0;}

Tipos compatíveis: note que o tipo de endereço que estamos passando para o ponteiro é int, uma vez que nosso ponteiro é do tipo inteiro. Se no lugar de a fosse atribuído um caracter por exemplo (char b), o programa não compilaria, pois estaríamos lidando com tipos incompatíveis.

Operador endereço: Uma vez que um ponteiro recebe um endereço de uma variável, foi preciso definir um operador que extraísse esse endereço. O operador que faz isso é o operador de endereço. &a significa “O endereço da variável a”.

Page 6: Revisão sobre ponteiros em C

Desenhos para analogiaA partir de agora, vamos pensar em variáveis como “caixinhas” que recebem valores dentro delas. Exemplo:

int main() {

int a = 10;

return 0;}

A representação destas variáveis ficariam assim:

10

a

&43jjuiop

a é o nome da caixa.

8 dígitos seguidos do símbolo de endereço, é o endereço desta caixa, chamado também de referência.

Valor da caixa

Um fato importante aqui:variáveis comuns só recebemvalores (int, char, float...). Umacaixa que representa umavariável comum nunca receberáum endereço como seu valor(apesar de que toda caixapossui um endereço dememória)

Page 7: Revisão sobre ponteiros em C

Desenhos para analogiaA partir de agora, vamos pensar em variáveis como “caixinhas” que recebem valores dentro delas. Exemplo:

int main() {

int a = 10;int* p = &a;

return 0;}

A representação da caixa de um ponteiro:

&43jjuiop

p

&98sd66dd

p é o nome da caixa.

Por ser uma variável, um ponteiro também precisa ser armazenada na memória e por isso tem um endereço de caixa.

Um fato importante aqui:variáveis ponteiros recebemsomente endereços e nãovalores! O conteúdo de umponteiro nunca será um int,char, etc. mas sim um endereçode um tipo. Para este caso, oendereço é do tipo inteiro(variável a é do tipo inteiro).

Endereço de a (valor que o ponteiro recebeu)

Page 8: Revisão sobre ponteiros em C

Desenhos para analogiaUma possível representação da relação entre ponteiro e varíavelpara qual ele aponta seria:

int main() {

int a = 10;int* p = &a;

return 0;}

&43jjuiop

p

&98sd66dd

10

a

&43jjuiop

O ponteiro aponta para a caixa de a, porque o endereço de a foi passado para ele. Uma característica do ponteiro importantíssima é que por apontar para a caixa de a, ele tem acesso ao seu valor (10) e pode alterá-lo a qualquer momento!

Page 9: Revisão sobre ponteiros em C

Características e funções de um ponteiro

Como dito, um ponteiro tem acesso ao valor da variável para qual ele aponta. Vamos ver como alterar esse valor através do ponteiro.

int main() {

int a = 10; int* p = &a;*p = 5;

return 0;}

10

a

&43jjuiop

1

2

3

Passo 1:

Variável a é criada.

Page 10: Revisão sobre ponteiros em C

Características e funções de um ponteiro

Como dito, um ponteiro tem acesso ao valor da variável para qual ele aponta. Vamos ver como alterar esse valor através do ponteiro.

int main() {

int a = 10; int* p = &a;*p = 5;

return 0;}

&43jjuiop

p

&98sd66dd

10

a

&43jjuiop

1

2

3

Passo 2:O ponteiro p é criado e o endereço de a é atribuído à ele. Portanto p aponta para a.

Page 11: Revisão sobre ponteiros em C

Características e funções de um ponteiro

Como dito, um ponteiro tem acesso ao valor da variável para qual ele aponta. Vamos ver como alterar esse valor através do ponteiro.

int main() {

int a = 10; int* p = &a;*p = 5;

return 0;}

&43jjuiop

p

&98sd66dd

10

a

&43jjuiop

1

2

3

Passo 3:O conteúdo de a é acessado e alterado utilizando o operador de acesso do ponteiro.

O conjunto *(nome_do_ponteiro) é o operador de acesso ao conteúdo da variável para qual o ponteiro aponta. Ao utilizarmos este operador, é possível alterar o valor da variável para o ponteiro aponta ou somente acessá-lo.

5

Page 12: Revisão sobre ponteiros em C

Passagem por referência

O exemplo anterior é somente uma demonstração. Utilizar um ponteiro para alterar o valor da variável neste caso não seria necessário, pois todo nosso programa está na main e conseguimos acessar esta variável a qualquer momento. Este fato muda, quando estamos trabalhando com funções. Lembre-se que as variáveis dentro do escopo de uma função, podem ser acessadas somente lá dentro. Portanto, se quisermos alterar o valor de uma variável que está na main dentro de uma função, a única maneira seria fazer esta função retornar o valor e atribuirmos este valor a variável para qual queremos alterar o valor. Vamos ver um exemplo.

Page 13: Revisão sobre ponteiros em C

Passagem por valor

Suponha que queremos alterar o valor de t utilizando uma função e sem utilizar ponteiros. Teríamos que fazer algo do tipo:

int main() {

int t = 10; t = valor(5);return 0;

}

int valor(int a) {

a = 5;return a;

}

O que acontece nesse caso é que t tinha 10 quando foi criado. Chamamos então a função valor com o novo valor que queremos para t (5) e atribuímos a chamada desta função para a variável t. Neste caso, quando o programa terminar t terá 5, que é o retorno função valor.

Page 14: Revisão sobre ponteiros em C

Passagem por valor

Lembrando, isto é só um exemplo, sem muita utilidade somente para entendermos os conceitos de passagem por valor e referência.

int main() {

int t = 10; t = valor(5);return 0;

}

int valor(int a) {

a = 5;return a;

}

Neste caso o que estamos fazendo, é passando um valor para função (para este exemplo o valor foi 5, mas poderia ter sido qualquer valor de inteiro). Tivemos que atribuir o valor de retorno para t, justamente porque a passagem de parâmetros para a função, foi feita através da passagem por valor. Quando utilizamos esta abordagem, tudo que acontece na função, tem alteração somente dentro dela e quando ela acaba, todos os valores gerados lá são destruídos e o que sobra é somente um retorno.

Page 15: Revisão sobre ponteiros em C

Passagem por valor

Vamos analisar um outro exemplo de passagem por valor. Vamos ver o que acontece quando tentamos alterar o valor de uma varíavel através de uma função que não tem retorno e utilizamos passagem por valor.

int main() {

int t = 10; valor(t);return 0;

}

void valor(int a) {a = 5;

} 1

2

3

4

5

Vamos ver a execução passo a passo.

Page 16: Revisão sobre ponteiros em C

Passagem por valor

Vamos analisar um outro exemplo de passagem por valor. Vamos ver o que acontece quando tentamos alterar o valor de uma varíavel através de uma função que não tem retorno e utilizamos passagem por valor.

int main() {

int t = 10; valor(t);return 0;

}

void valor(int a) {a = 5;

} 1

2

3

4

5

Passo 1

10

t

&43jjuiop

Page 17: Revisão sobre ponteiros em C

Passagem por valor

Vamos analisar um outro exemplo de passagem por valor. Vamos ver o que acontece quando tentamos alterar o valor de uma varíavel através de uma função que não tem retorno e utilizamos passagem por valor.

int main() {

int t = 10; valor(t);return 0;

}

void valor(int a) {a = 5;

} 1

2

3

4

5

Passo 2: a execução na main é interrompida e a função é chamada. O valor de t é enviado para a função.

10

t

&43jjuiop

10

Page 18: Revisão sobre ponteiros em C

Passagem por valor

Vamos analisar um outro exemplo de passagem por valor. Vamos ver o que acontece quando tentamos alterar o valor de uma varíavel através de uma função que não tem retorno e utilizamos passagem por valor.

int main() {

int t = 10; valor(t);return 0;

}

void valor(int a) {a = 5;

} 1

2

3

4

5

Passo 3: a variável que representa o parâmetro da função é criada. Note que o endereço de a é diferente do endereço de t.

10

t

&43jjuiop

10

10

a

&456699oo

Page 19: Revisão sobre ponteiros em C

Passagem por valor

Vamos analisar um outro exemplo de passagem por valor. Vamos ver o que acontece quando tentamos alterar o valor de uma varíavel através de uma função que não tem retorno e utilizamos passagem por valor.

int main() {

int t = 10; valor(t);return 0;

}

void valor(int a) {a = 5;

} 1

2

3

4

5

Passo 4: a variável a tem seu valor alterado para 5.

10

t

&43jjuiop

10

a

&456699oo

5

Page 20: Revisão sobre ponteiros em C

Passagem por valor

Vamos analisar um outro exemplo de passagem por valor. Vamos ver o que acontece quando tentamos alterar o valor de uma varíavel através de uma função que não tem retorno e utilizamos passagem por valor.

int main() {

int t = 10; valor(t);return 0;

}

void valor(int a) {a = 5;

} 1

2

3

4

5

Passo 5: a função termina e a execução na main é recomeçada e o programa se encerra. Neste momento nada que foi feito na função existe mais por que ela acabou.

10

t

&43jjuiop

Page 21: Revisão sobre ponteiros em C

Passagem por valor

O que aconteceu com a variável t que estava na main? NADA. Não tivemos sucesso em alterar seu valor desta vez, porque o que passamos para função foi somente o valor de t, que não tem nenhuma referência com a variável.

int main() {

int t = 10; valor(t);return 0;

}

void valor(int a) {a = 5;

} 1

2

3

4

5 10

t

&43jjuiop

Page 22: Revisão sobre ponteiros em C

Passagem por referência

Vamos então agora, tentar utilizar a passagem por referência. Referência para nós é o mesmo que endereço. Vamos então agora, passar o endereço de t para função e não mais seu valor. Vamos alterar as funções para que isto ocorra.

int main() {

int t = 10; valor(&t);return 0;

}

void valor(int* a) {

*a = 5;}

1

2

3

4

5

Vamos novamente analisar a execução passo a passo.

Page 23: Revisão sobre ponteiros em C

Passagem por referência

Vamos então agora, tentar utilizar a passagem por referência. Referência para nós é o mesmo que endereço. Vamos então agora, passar o endereço de t para função e não mais seu valor. Vamos alterar as funções para que isto ocorra.

int main() {

int t = 10; valor(&t);return 0;

}

void valor(int* a) {

*a = 5;}

1

2

3

4

5

Passo 1

10

t

&43jjuiop

Page 24: Revisão sobre ponteiros em C

Passagem por referência

Vamos então agora, tentar utilizar a passagem por referência. Referência para nós é o mesmo que endereço. Vamos então agora, passar o endereço de t para função e não mais seu valor. Vamos alterar as funções para que isto ocorra.

int main() {

int t = 10; valor(&t);return 0;

}

void valor(int* a) {

*a = 5;}

1

2

3

4

5

Passo 2

10

t

&43jjuiop

Passo 2: a execução na main é interrompida e a função é chamada. Agora, a caixinha que está sendo mandada para a função possui o endereço de t e não mais o seu valor.

&43jjuiop

Page 25: Revisão sobre ponteiros em C

Passagem por referência

Vamos então agora, tentar utilizar a passagem por referência. Referência para nós é o mesmo que endereço. Vamos então agora, passar o endereço de t para função e não mais seu valor. Vamos alterar as funções para que isto ocorra.

int main() {

int t = 10; valor(&t);return 0;

}

void valor(int* a) {

*a = 5;}

1

2

3

4

5

10

t

&43jjuiop

Passo 3: a variável a é criada. Note que ela é um ponteiro e não poderia ser diferente, pois passamos para a função um endereço e relembrando: variáveis que recebem endereços são ponteiros! Desta forma a aponta para t!

&43jjuiop

a

&4558899

Page 26: Revisão sobre ponteiros em C

Passagem por referência

Vamos então agora, tentar utilizar a passagem por referência. Referência para nós é o mesmo que endereço. Vamos então agora, passar o endereço de t para função e não mais seu valor. Vamos alterar as funções para que isto ocorra.

int main() {

int t = 10; valor(&t);return 0;

}

void valor(int* a) {

*a = 5;}

1

2

3

4

5

10

t

&43jjuiop

Passo 4: o operador de acesso é utilizado para alterar o conteúdo da variável para qual a aponta. Neste caso então o valor da variável t será alterado de 10 para 5.

&43jjuiop

a

&4558899

5

Page 27: Revisão sobre ponteiros em C

Passagem por referência

Vamos então agora, tentar utilizar a passagem por referência. Referência para nós é o mesmo que endereço. Vamos então agora, passar o endereço de t para função e não mais seu valor. Vamos alterar as funções para que isto ocorra.

int main() {

int t = 10; valor(&t);return 0;

}

void valor(int* a) {

*a = 5;}

1

2

3

4

5

5

t

&43jjuiop

Passo 5: a função termina e a execução, todas as suas variáveis são destruídas, a execução na main é continuada e o programa então se encerra.

Page 28: Revisão sobre ponteiros em C

Passagem por referência

O que aconteceu com a variável t? Teve seu valor alterado, mesmo não estando dentro da função. Isso só foi possível, porque passamos uma referência (endereço) de t para a função e quando passamos uma referência, podemos utilizar o operador de acesso para acessar ou alterar o valor da variável onde quer que ela esteja, pois temos um link com a mesma.

int main() {

int t = 10; valor(&t);return 0;

}

void valor(int* a) {

*a = 5;}

5

t

&43jjuiop

Page 29: Revisão sobre ponteiros em C

Passagem por referência

É claro que este foi um exemplo muito simples e parece inútil esta função para nós por agora. Porém, quando entrarmos em TAD, ficará claro como, utilizar a passagem por referência utilizando ponteiros, diminuirá a complexidade de nossas funções e evitará que a todo momento tenhamos que fazer re-atribuições de variáveis, o que pode tornar o código ineficiente e time-costing.