Ponteiros e Vetores
INF01202
Sumário
Ponteiros
I
Aritmética de ponteiros (lembrete)
I
Exemplo #1: aritmética
Ponteiros e vetores
I
Semelhanças
I
Exemplo #2
I
Diferenças
I
Exemplo #3
I
Exemplo #4
Passagem de vetores como referência
I
Exemplo #5 (leitura de valores)
I
Exemplo #6 (manipulação de string)
I
Exemplo #7 (copia invertido)
Aritmética de ponteiros (lembrete)
9 INF 01202 - Prof. Marcelo Walter – Aula 19
Aritmética de Ponteiros
– Supondo um ponteiro inteiro p1, apontando para o
endereço de memória 2000: • p1++; // valor de p1 fica 2004 * • p1--; // valor de p1 fica 1996
• p1= p1 + 5; // p1 passa a apontar para 2000 + (5 X 4) * Cada inteiro ocupa 4 bytes neste exemplo. Isto varia de
arquitetura para arquitetura
2000 2004
2000
p1 2000 20042004
p1Após p1++
Memória EndereçosExemplo #1 a28-aritmetica.c
#include <stdio.h> int main() {
int i, *pi1, *pi2;
double d, *pd1, *pd2; char c, *pc1, *pc2; c = 'A'; d = 5.423; i = -20; pi1 = &i;
pi2 = pi1 + 1; // incrementa o espaco ocupado por um inteiro (4 bytes)
pd1 = &d;
pd2 = pd1 + 2; // incrementa duas vezes o espaco ocupado por um double (2*8 bytes)
pc1 = &c;
pc2 = pc1 - 1; // decrementa o espaco ocupado por um char (1 byte)
printf("Resultados em hexadecimal\n"); printf("pi1: %p, pi2: %p\n", pi1, pi2); printf("pd1: %p, pd2: %p\n", pd1, pd2); printf("pc1: %p, pc2: %p\n\n", pc1, pc2); printf("Resultados em decimal\n"); printf("pi1: %d, pi2: %d\n", pi1, pi2); printf("pd1: %d, pd2: %d\n", pd1, pd2); printf("pc1: %d, pc2: %d\n", pc1, pc2);
Ponteiros e vetores:
semelhanças
11 INF 01202 - Prof. Marcelo Walter – Aula 19
Semelhanças entre Ponteiros e Vetores
• O nome de um vetor corresponde a um ponteiro constante, istoé,
ao ponteiro para o primeiro elemento
. • Em geral, as operações válidas para ponteiros podem serexecutadas com vetores.
• Assim, as notações abaixo são equivalentes:
com vetores equivale a com ponteiros int v[100]; int *v;
v[i] ou *(v+i) *(v+i) ou v[i] &v[i] v+i
declaração de
vetor v
de inteiros com 100 elementos indica quevé umponteiroque aponta para o 1º elemento do vetor(v[0]),alocando a área necessáriadeclaração do
ponteiro v
apontapara a posiçãoinicial, mas
não aloca áreapara isso.
Exemplo #2 a28-semelhancas.c
#include <stdio.h>
#define TAM 2
int main() {
int v[TAM]; //alocação de vetor de inteiros de tamanho TAM int i;
printf("Leitura com acesso tipo ponteiro\n");
for (i = 0; i < TAM; i++)
scanf("%d",v+i); // ja eh ponteiro (sem o "e" comercial)
printf("Impressao com acesso tipo ponteiro\n");
for (i = 0; i < TAM; i++)
printf("%d ",*(v+i)); //acessamos o valor apontado por v+i
printf("\n");
printf("Impressao com acesso tipo vetor\n");
for (i = 0; i < TAM; i++)
printf("%d ",v[i]); //acessamos a posição i de v
printf("\n");
return 0; }
Ponteiros e vetores:
diferenças
(na declaração unicamente)
13 INF 01202 - Prof. Marcelo Walter – Aula 19
Diferença entre Ponteiros e Vetores
•
Declaração de
vetor
:
–
o compilador automaticamente
reserva um bloco de
memória
para que o vetor seja armazenado,
do tamanho
especificado na declaração
(mas não controla se o uso é
limitado à área reservada).
•
Declaração de
ponteiro
:
–
o compilador
aloca um ponteiro
para apontar para a
memória,
sem reservar espaço de memória
(usado para
alocação dinâmica de memória).
Por exemplo, considere:
int v[3]={1,2,3}; int *p;
p = v; //operação válida. Atribui a p o end do 1º elem de v v = p; //operação inválida (pois v aponta para um endereço fixo de memória)
Exemplo #3 a28-diferencas.c
#include <stdio.h> #define TAM 3 int main() { int v[TAM] = {1,2,3}; int *p;p = v; //operação válida. Atribui a p o endereço do primeiro elemento de v
v = p; //operação inválida (pois v aponta para um endereço fixo de memória) return 0;
}
Compilando para ver
error
gcc a28-diferencas.c 2> x; cat x a28-diferencas.c: In function `main':
a28-diferencas.c:9:5: error: assignment to expression with array type
v = p; //operação inválida (pois v aponta para um endereço fixo de memória) ^
Exemplo #3 a28-diferencas.c
#include <stdio.h> #define TAM 3 int main() { int v[TAM] = {1,2,3}; int *p;p = v; //operação válida. Atribui a p o endereço do primeiro elemento de v
v = p; //operação inválida (pois v aponta para um endereço fixo de memória) return 0;
}
Compilando para ver
error
gcc a28-diferencas.c 2> x; cat x a28-diferencas.c: In function `main':
a28-diferencas.c:9:5: error: assignment to expression with array type
v = p; //operação inválida (pois v aponta para um endereço fixo de memória) ^
Exemplo #4 a28-strings.c
Strings são vetores de caracteres.
#include <stdio.h> int main() {
char str[80] = "Alpha Centauri";
char *p1;
//atribui à p1 o endereço do primeiro elemento de str
p1 = str;
//imprimir o mesmo elementos com dois atalhos
printf("[%c] = [%c]\n", str[0], *p1);
// str[4] ou *(p1+4) acessam o 5o caractere (elemento) de str
printf("[%c] = [%c]\n", str[4], *(p1+4));
return 0; }
Resumo: Vetores são como se fossem ponteiros!
Slide 7 INF 01202
•
Uma variável que representa um vetor
corresponde a um endereço de memória.
Assim:
–
Vetores
são SEMPRE
passados por referência
!
–
Alterações feitas no vetor dentro da subrotina
modificam o mesmo
após a saída da subrotina!
–
Apenas
o endereço do primeiro elemento do vetor
é passado (v, ou equivalentemente, &v[0])
•
Dessa forma, o tamanho (comprimento) do
vetor também deve ser passado explicitamente
como argumento para a subrotina.
Vetores e parâmetros de funções
Exemplo #5 a28-levetor.c (leitura de valores)
Faça uma função le_vetor de oats que receba como parâmetro o vetor
a ser preenchido e o número de elementos a serem lidos:
#include <stdio.h>
#define TAM 3
void le_vetor(float vetor[], int num_vet) { //leitura de um vetor de floats int i; // variável local, para auxiliar leitura
printf("Entre os %d valores do vetor, separados por espaços\n",num_vet);
for (i = 0; i < num_vet; i++) scanf("%f",&vetor[i]);
return; }
int main() {
int i; //contador float vec[TAM];
printf("leitura de %d elementos \n", TAM);
le_vetor(vec, TAM); //<-- veja a chamada da função for (i = 0; i < TAM; i++) // escrita do vetor
printf("%.2f ", vec[i]); printf("\n");
return 0; }
Exemplo #5 a28-levetor.c (leitura de valores)
Faça uma função le_vetor de oats que receba como parâmetro o vetor
a ser preenchido e o número de elementos a serem lidos:
#include <stdio.h>
#define TAM 3
void le_vetor(float vetor[], int num_vet) { //leitura de um vetor de floats int i; // variável local, para auxiliar leitura
printf("Entre os %d valores do vetor, separados por espaços\n",num_vet);
for (i = 0; i < num_vet; i++) scanf("%f",&vetor[i]);
return; }
int main() {
int i; //contador float vec[TAM];
printf("leitura de %d elementos \n", TAM);
le_vetor(vec, TAM); //<-- veja a chamada da função for (i = 0; i < TAM; i++) // escrita do vetor
printf("%.2f ", vec[i]); printf("\n");
return 0; }
Observação sobre o Exemplo #5
Slide 9 INF 01202
Exercício 1 : função void, para leitura de um vetor:
• Exemplo de execução
Observação:
• A declaração void le_vetor(float vetor[ ], int num_vet)
Exemplo #6 a28-upper.c (manipulação de string)
Faça uma função void que receba como parâmetro uma string e converta
todos seus caracteres para maiúsculas.
#include <stdio.h>
void nosso_upper (char str[]) {
int i = 0; //contador inicializado na primeira posicao da string while(str[i] != '\0') {
str[i] = toupper(str[i]); i++;
} }
Uma segunda versão:
void nosso_upper_v2 (char str[]) {
while(*str != '\0'){
*str = toupper(*str); str++;
} }
Exemplo #6 a28-upper.c (manipulação de string)
Faça uma função void que receba como parâmetro uma string e converta
todos seus caracteres para maiúsculas.
#include <stdio.h>
void nosso_upper (char str[]) {
int i = 0; //contador inicializado na primeira posicao da string while(str[i] != '\0') {
str[i] = toupper(str[i]); i++;
} }
Uma segunda versão:
void nosso_upper_v2 (char str[]) {
while(*str != '\0'){
*str = toupper(*str); str++;
} }
Exemplo #7 a28-inverte.c (copia invertido)
Faça uma função void inverte(char* str1, char* str2), que copie
o conteúdo de str1 invertido (caracteres de trás para frente) em str2.
#include <stdio.h>
#include <string.h>
#define TAM 20
void inverte(char* str1, char* str2);
int main() {
char c1[TAM], c2[TAM]; fgets(c1, TAM, stdin); c1[strlen(c1)-1] = '\0'; inverte_texto(c1, c2);
printf("[%s] -> [%s]\n", c1, c2);
return 0; }
void inverte(char* str1, char* str2) {
int i, n = strlen(str1);
for (i = 0; i < n; i++) str2[i] = str1[n - 1 - i]; str2[i] = '\0';
Exemplo #7 a28-inverte.c (copia invertido)
Faça uma função void inverte(char* str1, char* str2), que copie
o conteúdo de str1 invertido (caracteres de trás para frente) em str2.
#include <stdio.h>
#include <string.h>
#define TAM 20
void inverte(char* str1, char* str2);
int main() {
char c1[TAM], c2[TAM]; fgets(c1, TAM, stdin); c1[strlen(c1)-1] = '\0'; inverte_texto(c1, c2);
printf("[%s] -> [%s]\n", c1, c2);
return 0; }
void inverte(char* str1, char* str2) {
int i, n = strlen(str1);
for (i = 0; i < n; i++) str2[i] = str1[n - 1 - i]; str2[i] = '\0';
Exemplo #8 a28-maior.c (ponteiro para maior)
Uma função também pode retornar um ponteiro
Escreva uma função em C que receba como parâmetro um vetor de
inteiros, e retorne um ponteiro apontando para a posição do maior
elemento do vetor
#include <stdio.h>
// função tipo ponteiro inteiro int *maior(int vet[], int tamanho) {
int i, *p; // índice e ponteiro de elemento do vetor
p = vet; // aponta para 1o elemento do vetor for (i = 0; i < tamanho; i++)
if (vet[i] > *p)
p = vet + i; // passa a apontar para o maior valor return p; // retorna o ponteiro
}
int main() {
int vet[] = {3, 1, 8, 4}, *m = NULL; m = maior (vet, 4);
return 0; }
Exemplo #8 a28-maior.c (ponteiro para maior)
Uma função também pode retornar um ponteiro
Escreva uma função em C que receba como parâmetro um vetor de
inteiros, e retorne um ponteiro apontando para a posição do maior
elemento do vetor
#include <stdio.h>
// função tipo ponteiro inteiro int *maior(int vet[], int tamanho) {
int i, *p; // índice e ponteiro de elemento do vetor
p = vet; // aponta para 1o elemento do vetor for (i = 0; i < tamanho; i++)
if (vet[i] > *p)
p = vet + i; // passa a apontar para o maior valor return p; // retorna o ponteiro
}
int main() {
int vet[] = {3, 1, 8, 4}, *m = NULL; m = maior (vet, 4);
return 0; }
Exemplo #8 a28-maior.c (ponteiro para maior)
Uma função também pode retornar um ponteiro
Escreva uma função em C que receba como parâmetro um vetor de
inteiros, e retorne um ponteiro apontando para a posição do maior
elemento do vetor
#include <stdio.h>
// função tipo ponteiro inteiro int *maior(int vet[], int tamanho) {
int i, *p; // índice e ponteiro de elemento do vetor
p = vet; // aponta para 1o elemento do vetor for (i = 0; i < tamanho; i++)
if (vet[i] > *p)
p = vet + i; // passa a apontar para o maior valor return p; // retorna o ponteiro
}
int main() {
int vet[] = {3, 1, 8, 4}, *m = NULL; m = maior (vet, 4);
return 0; }
Observação sobre o Exemplo #8
Slide 17 INF 01202