Ponteiros em C. Adriano Joaquim de Oliveira Cruz 21 de julho de Instituto de Matemática Departamento de Ciência da Computação UFRJ

Documentos relacionados
Ponteiros. Introdução

Exercício. Alocação Dinâmica. Alocação dinâmica de memória. Alocação de memória. Alocação da Memória Principal. Alocação da Memória Principal

Introdução a Programação. Ponteiros e Strings, Alocação Dinâmica

Exercícios. Alocação Dinâmica. Alocação dinâmica de memória. Alocação de memória. Alocação da Memória Principal. Alocação da Memória Principal

1/34 GESTÃO DINÂMICA DE MEMÓRIA

Ponteiros. Introdução e Alocação Dinâmica

SSC304 Introdução à Programação Para Engenharias. Ponteiros. GE4 Bio

Métodos Computacionais. Vetores e Matrizes Dinâmicas

Reinaldo Gomes Alocação Dinâmica

Universidade Federal de Uberlândia Faculdade de Computação. Linguagem C: ponteiros e alocação dinâmica

Introdução a Programação. Ponteiros e Vetores, Alocação Dinâmica

Alocação Dinâmica em C

1 Exercícios com ponteiros

Aula 17: Ponteiros e Alocação Dinâmica em C

ED1 - Aula 01 Introducao e revisão

Ponteiros - Parte I. Ponteiros, Ponteiros e Vetores, Algoritmo Bubble Sort, Alocação Dinâmica de Memória

Ponteiros. Baseado nos slides do Prof. Mauro.

1 Exercícios com ponteiros

Alocação Dinâmica. Introdução à Computação

ALGORITMOS E ESRUTRA DE DADOS I. Ponteiros Passagem por Valor e Referência Alocação de Memória

A linguagem C permite dois tipos de alocação de memória: Alocação estática e alocação dinâmica.

Estruturas de Dados. Profa. Juliana Pinheiro Campos

Ponteiros e alocação dinâmica de memória. Disciplina de Programação de Computadores I Universidade Federal de Ouro Preto

INF 1007 Programação II

Programação II. Vetores e Alocação Dinâmica. Bruno Feijó Dept. de Informática, PUC-Rio

Estruturas de Dados Aulas 3 e 4: Uso da. 14/03/2011 e 16/03/2011

13. ALOCAÇÃO DINÂMICA DE MEMÓRIA

Ponteiros e Tabelas. K&R: Capitulo 5 IAED, 2012/2013

Ponteiros e Tabelas. K&R: Capitulo 5 IAED, 2012/2013

Programação II. Vetores e Alocação Dinâmica. Bruno Feijó Dept. de Informática, PUC-Rio

Computação 2. Aula 7. Profª. Fabiany Ponteiros

Programação Estruturada

Ponteiros e Alocação de Memória

1. Revisão de Vetores, Ponteiros, Funções e Estruturas em C

Estruturas de Dados. Introdução Definição de Ponteiros Declaração de Ponteiros em C Manipulação de Ponteiros em C

LINGUAGEM C: PONTEIROS

Estruturas Dinâmicas - Ponteiros

Aula 25: Alocação Dinâmica

Linguagem C: Ponteiros. Prof. Tiago Alves de Oliveira

Linguagem C. Ponteiros. Alex Vidigal Bastos.

Linguagem C: Ponteiros. Prof. Leonardo Barreto Campos 1

Estruturas de Dados Aulas 3 e 4: Uso da memória e Vetores

3. Linguagem de Programação C

Ponteiros. prof. Fabrício Olivetti de França

O que é um apontador em C (type pointer in C)?

Programação. Cap. 12 Gestão de Memória Dinâmica

Introdução à Ciência da Computação I. Alocação Dinâmica. Prof. Claudio Fabiano Motta Toledo

Princípios de Desenvolvimento de Algoritmos MAC122

Aula 24 Ponteiros, vetores e structs

REVISÃO DE C. Vanessa Braganholo Estruturas de Dados e Seus Algoritmos

11a. Aula Ponteiros e Vetores

SSC304 Introdução à Programação Para Engenharias. Alocação Dinâmica. GE4 Bio

Computadores Digitais 2. Prof. Rodrigo de Souza Couto

Módulo 5 Vetores e Alocação Dinâmica

Ponteiros & tabelas (cont.) K&R: Capítulo 5

Ponteiros e Tabelas. K&R: Capítulo 5

Estruturas da linguagem C. 1. Identificadores, tipos primitivos, variáveis e constantes, operadores e expressões.

Programação I Ponteiros e alocação dinâmica de memória. Prof. Carlos Alberto

A sintaxe para se declarar uma variável do tipo ponteiro é dada por:

Linguagem C Ponteiros

ponteiros INF Programação I Prof. Roberto Azevedo

5. Vetores e alocação dinâmica

Algoritmos e Estruturas de Dados. Prof. Marcelo Zorzan Profa. Melissa Zanatta

Introdução a Programação de Jogos

Alocação Dinâmica de Memória - Exercício

PONTEIROS E LISTAS. Kalinka Regina Lucas Jaquie Castelo Branco

Introdução. Ponteiros

Estruturas de Dados Homogêneas (Vetores e Matrizes) e Ponteiros em C

Matrizes em C. Lucas Ferrari de Oliveira Professor Adjunto. Universidade Federal do Paraná

C Estruturas. Adriano Cruz 21 de julho de Instituto de Matemática Departamento de Ciência da Computação UFRJ

Programação Mestrado Integrado em Engenharia Aeronáutica 1º ano, 1º semestre. T. 11 Gestão de Memória Dinâmica

TÉCNICAS DE LINGUAGEM DE PROGRAMAÇÃO

LÓGICA DE PROGRAMAÇÃO (C) VETORES E MATRIZES. Professor Carlos Muniz

Linguagem C Apontadores. Endereços e apontadores Passagem de parâmetros para funções Apontadores e vectores Memória dinâmica

Alocação dinâmica de Memória

Programação: Vetores

Ponteiros. Ponteiros. Ponteiros. Ponteiros. Ponteiros. Introdução a Programação. Profa. Roseli Romero

INF1007: Programação 2. 2 Alocação Dinâmica. 17/02/2014 (c) Dept. Informática - PUC-Rio 1

Estrutura de dados 1. Ponteiros

Programação Estruturada Prof. Rodrigo Hausen Organização e Gerenciamento de Memória

Introdução à Programação. Operadores, Expressões Aritméticas e Entrada/Saída de Dados

Introdução à Computação

Métodos Computacionais. Operadores, Expressões Aritméticas e Entrada/Saída de Dados

Sumário. Introdução à Ciência da Computação. Ponteiros em C. Introdução. Definição. Por quê ponteiros são importantes?

Vetores e Strings. 6. Comandos de entrada e saída formatada que trabalham sobre strings

Introdução à Computação

Programação de Computadores II. Cap. 5 Alocação Dinâmica

DAS5102 Fundamentos da Estrutura da Informação

Ponteiros. um ponteiro é uma variável que contém o endereço um dado declaração: * indica que a variável é um ponteiro. Ex: tipo_dado *nome_ponteiro;

AULA 6. Conceitos. Melhores momentos. Conceitos. Conceitos. Conceitos. Conceitos

Capítulo 1: Introdução à Linguagem C. Pontifícia Universidade Católica Departamento de Informática

Introdução a Computação

Ponteiros e Alocação Dinâmica em C. Fonte: DCC UFMT (modificado)

LINGUAGEM C: ALOCAÇÃO DINÂMICA

Tipos Básicos. Operadores de Incremento e Decremento. Operador Sizeof. Estruturas de Dados Aula 2: Estruturas Estáticas

ESTRUTURA DE DADOS (TCC )

Transcrição:

Ponteiros em C Adriano Joaquim de Oliveira Cruz 21 de julho de 2017 Instituto de Matemática Departamento de Ciência da Computação UFRJ 1

Resumo da Seção Introdução Declaração Incrementando e Decrementando Ponteiros Ponteiros e Vetores Alocação Dinâmica de Memória Ponteiros e Matrizes Vetores de Ponteiros Ponteiros para ponteiros 2

Bibliografia 1. Adriano Cruz. Curso de Linguagem C, Disponível em http://equipe.nce.ufrj.br/adriano 2. Ulysses de Oliveira. Programando em C, Editora Ciência Moderna. 3

Ponteiros? 4

Ponteiros (Endereços) apontam 5

lugares na memória 6

para buscarmos dados. 7

Quando usar? Ponteiros são importantes quando se deseja que uma função retorne mais de um valor. A função deve receber como argumentos não os valores dos parâmetros mas sim ponteiros que apontem para seus endereços. Com os endereços é possível modificar diretamente os conteúdos destas variáveis. 8

Quando usar? Outra aplicação é apontar para áreas de memória que devem ser gerenciadas durante a execução do programa. Por exemplo, vetores de tamanhos desconhecidos. Com ponteiros, é possível reservar as posições de memória necessárias para estas áreas. 9

Resumo da Seção Introdução Declaração Incrementando e Decrementando Ponteiros Ponteiros e Vetores Alocação Dinâmica de Memória Ponteiros e Matrizes Vetores de Ponteiros Ponteiros para ponteiros 10

Definindo Antes de serem usados os ponteiros, como as variáveis, precisam ser declarados. A forma geral da declaração de um ponteiro é a seguinte: tipo *nome; Onde tipo é qualquer tipo válido em C e nome é o nome da variável ponteiro. O asterisco indica que a variável irá armazenar endereço e não dado. 11

Exemplos int res; / ponteiro para inteiro / float div; / ponteiro para ponto flutuante / char c; / ponteiro para caractere / 12

Inicializando Como as variáveis, os ponteiros devem ser inicializados antes de serem usados. Esta inicialização pode ser feita na declaração ou através de uma atribuição. Após a declaração o que temos é um espaço na memória reservado para armazenamento de endereços. O valor inicial da memória é indefinido como acontece com variáveis. 13

Variáveis que... Endereços int num; int *pint; Lixo num = 20; 0X00 0X04 0X08 0X0C 0X10 @#$% &*()!@ 20 num $&(!@#*+- *pint $&(!@#*+- num *pint 0X00 0X04 0X08 0X0C 0X10 N N Isto é uma memória 14

Variáveis que armazenam endereços... num = 20; num = 20; pint = # 0X00 0X04 0X08 0X0C 0X10 20 num $&(!@#*+- *pint 0X00 0X04 0X08 0X0C 0X10 20 num 0X04 *pint N N 15

Operadores Especiais Existem dois operadores especiais para ponteiros: e &. Os dois operadores são unários, isto é requerem somente um operando. O operador & devolve o endereço de memória do seu operando. O operador devolve o valor da variável localizada no endereço apontado pelo ponteiro. 16

Exemplo #include<stdio.h> int main (void ) { int i = 10; int p; p = &i; p = p + 1; printf( %d\n, i) ; return 0; 17

Atribuições com ponteiros Da mesma maneira que ocorre com uma variável comum, o conteúdo de um ponteiro pode ser passado para outro ponteiro do mesmo tipo. Por exemplo, uma variável ponteiro declarada como apontador de dados inteiros deve sempre apontar para dados deste tipo. Observar que em C é possível atribuir qualquer endereço a uma variável ponteiro. Deste modo é possível atribuir o endereço de uma variável do tipo float a um ponteiro do tipo int. No entanto, o programa não irá funcionar da maneira correta. 18

Exemplo #include <stdio.h> int main( void ) { int vetor [] = { 10, 20, 30, 40, 50 ; int p1, p2; int i = 100; p1 = &vetor [2]; printf( %d\n, p1) ; p2 = &i; printf( %d\n, p2) ; p2 = p1; printf( %d\n, p2) ; return 0; 19

Incrementando/Decrementando ponteiros int main( void ) { int vetor [] = { 10, 20, 30, 40, 50 ; int p1; p1 = &vetor [2]; printf( %d\n, p1) ; p1++; printf( %d\n, p1) ; p1 = p1 + 1; printf( %d\n, p1) ; return 0; 20

Incrementando/Decrementando ponteiros Um ponteiro para um número inteiro, que é armazenado em quatro bytes, é incrementado por um e aponta para o próximo número inteiro. Não deveria ser de 4? O compilador interpreta o comando p1++ como: passe a apontar para o próximo número inteiro e, portanto, aumenta automaticamente o endereço do número de bytes correto. Este ajuste é feito de acordo com o tipo do operando que o ponteiro está apontando. Do mesmo modo, somar três a um ponteiro faz com que ele passe apontar para o terceiro elemento após o atual. 21

Operações Aritméticas A diferença entre ponteiros fornece quantos elementos do tipo do ponteiro existem entre os dois ponteiros. No exemplo é impresso o valor 2. #include <stdio.h> int main(void) { float vetor[] = { 1.0, 2.0, 3.0, 4.0, 5.0 ; float *p1, *p2; p1 = &vetor[2]; /* endereco do terceiro elemento */ p2 = vetor; /* endereco do primeiro elemento */ printf("diferenca entre ponteiros %d\n", p1-p2); return 0; 22

Operações Aritméticas: não usar Não é possível multiplicar ou dividir ponteiros. Não se pode adicionar ou subtrair o tipo float ou o tipo double a ponteiros. É possível comparar ponteiros em uma expressão relacional. No entanto, só é possível comparar ponteiros de mesmo tipo. 23

Resumo da Seção Introdução Declaração Incrementando e Decrementando Ponteiros Ponteiros e Vetores Alocação Dinâmica de Memória Ponteiros e Matrizes Vetores de Ponteiros Ponteiros para ponteiros 24

Ponteiros e Vetores Ponteiros e Vetores estão fortemente relacionados na linguagem C. O nome de um vetor é um ponteiro que aponta para a primeira posição do vetor. Este é um valor que não pode ser alterado. A declaração int vetor[100] cria um vetor de inteiros de 100 posições e permite que algumas operações com ponteiros possam ser realizadas com a variável vetor. No entanto, existe uma diferença fundamental entre declarar um conjunto de dados como um vetor ou através de um ponteiro. 25

Ponteiros e Vetores Na declaração de vetor, o compilador automaticamente reserva um bloco de memória para que o vetor seja armazenado. Quando apenas um ponteiro é declarado a única coisa que o compilador faz é alocar um ponteiro para 26

Ponteiros e Vetores #include<stdio.h> int main( void ) { float v[] = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0; int i; for (i = 0; i < 7; i++) { printf( %.1f, v[i]) ; printf( \n ) ; for (i = 0; i < 7; i++) { printf( %.1f, (v+i)) ; return 0; 27

Ponteiros e Vetores Para percorrer um vetor também é possível usar um ponteiro variável. int pv; Observar que o nome de um vetor de tamanho fixo é um ponteiro constante. int v[10] Ponteiros constantes não podem ser alterados. Ponteiros variáveis podem ser alterados. 28

Ponteiros Variáveis #include <stdio.h> int main(void) { float v[] = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0; int i; float *p; for (i = 0; i < 7; i++) printf("%.1f ", v[i]); printf("\n"); for (i = 0; i < 7; i++) printf("%.1f ", *(v+i)); printf("\n"); for (i = 0, p = v; i < 7; i++, p++) { printf("%.1f ", *p); return 0; 29

Ponteiros Variáveis #include<stdio.h> int strcop(char d, char o) ; int main( void ) { char destino [20]; char origem= cadeia de caractere de origem ; strcop(destino, origem) ; printf( %s\n, origem) ; printf( %s\n, destino) ; return 0; int strcop(char d, char o) { while (( d++ = o++)!= '\0 ') ; return 0; 30

Resumo da Seção Introdução Declaração Incrementando e Decrementando Ponteiros Ponteiros e Vetores Alocação Dinâmica de Memória Ponteiros e Matrizes Vetores de Ponteiros Ponteiros para ponteiros 31

Alocação Dinâmica O uso de ponteiros e vetores exige que após a definição da variável ponteiro uma área de memória deve ser reservada para armazenar os dados do vetor. Para obter esta área o programa deve usar funções existentes na biblioteca stdlib. Estas funções pedem ao sistema operacional para separar pedaços da memória e devolvem ao programa que pediu o endereço inicial deste local. 32

Funções para Alocação As funções básicas de alocação de memória que iremos discutir são: void malloc(size_t size); Reserva size bytes na memória para algum item de um programa. O valor armazenado no espaço é indefinido. A função retorna um ponteiro de tipo void para o espaço reservado ou NULL no caso de algum erro ocorrer. void calloc(size_t num, size_t size); Reserva espaço na memória para um vetor de num itens do programa. Cada item tem tamanho size. Todos os bits do espaço são inicializados com 0. A função retorna um ponteiro de tipo void para o espaço reservado ou NULL no caso de algum erro ocorrer. 33

Funções para Desalocação void free(void pont); O espaço apontado por pont é devolvido ao sistema para uso. Caso pont seja um ponteiro nulo nenhuma ação é executada. No caso do ponteiro não ter sido resultado de uma reserva feita por meio de uma das funções calloc, realloc ou malloc o resultado é indefinido. 34

Mudando o tamanho do vetor void realloc(void pont, size_t size); A função altera o tamanho do objeto na memória apontado por pont para o tamanho especificado por size. O conteúdo do objeto será mantido até um tamanho igual ao menor dos dois tamanhos, novo e antigo. Se o novo tamanho requerer movimento, o espaço reservado anteriormente é liberado. Caso o novo tamanho for maior, o conteúdo da porção de memória reservada a mais ficará com um valor sem especificação. Se o tamanho size for igual a 0 e pont não é um ponteiro nulo o objeto previamente reservado é liberado. 35

Usando calloc #include <stdio.h> #include <stdlib.h> int main(void) { float *v; int i, tam; printf("qual o tamanho do vetor? "); scanf("%d", &tam); v = calloc(tam, sizeof(float)); if (!v) { return 1; for (i=0; i<tam; i++) { printf("elemento %d?", i); scanf("%f", v+i); printf("li valor %f \n", *(v+i)); free(v); return 0; 36

Ponteiros Variáveis #include <stdio.h> #include <stdlib.h> void LeVetor (float *v, int tam); float ProcuraMaior (float *v, int tam, int *vezes); int main(void) { float *v, maior; int i, tam, vezes; printf("qual o tamanho do vetor? "); scanf("%d", &tam); v = (float *) malloc(tam * sizeof(float)); if (!v) return 1; LeVetor(v, tam); maior = ProcuraMaior (v, tam, &vezes); printf("maior = %f e aparece %d vezes.\n.", maior, vezes); free(v); return 0; 37

Ponteiros Variáveis void LeVetor (float *v, int tam) { int i; for (i=0; i<tam; i++) { scanf("%f", v+i); float ProcuraMaior (float *v, int tam, int *vezes) { int i; float maior; maior = v[0]; *vezes = 1; for (i=1; i<tam; i++) { if (v[i] > maior) { maior = v[i]; *vezes = 1; else if (maior == v[i]) *vezes=*vezes+1; return maior; 38

Resumo da Seção Introdução Declaração Incrementando e Decrementando Ponteiros Ponteiros e Vetores Alocação Dinâmica de Memória Ponteiros e Matrizes Vetores de Ponteiros Ponteiros para ponteiros 39

Matrizes e Ponteiros Um ponteiro aponta para uma área de memória que é endereçada de maneira linear. Vetores podem ser facilmente manipulados com ponteiros. Em estruturas de dados com maior dimensionalidade, como matrizes, por exemplo, que são arranjos bidimensionais de dados, é necessário mapear o espaço bidimensional (ou de maior ordem) para uma dimensão. No caso das matrizes é necessário mapear o endereço de cada elemento na matriz, que é definido por um par (linha, coluna) em um endereço linear. 40

Matrizes e Ponteiros Considere uma matriz chamada matriz de tamanho LIN,COL Podemos usar uma solução que mapeie a matriz que é um objeto de duas dimensões em um vetor que tem apenas uma. Neste caso o programa deve fazer a translação de endereços toda vez que precisar ler ou escrever na matriz. A expressão matriz+(i COL+j) calcula a posição do elemento matriz[i][j] a partir do primeiro elemento da matriz que está no endereço inicial matriz. 41

Matrizes que são vetores #define LIN 3 #define COL 4 int *matriz; int i, j; matriz = malloc(lin*col*sizeof(int)); if (!matriz) { printf("erro.\n"); return 1; for(i = 0; i < LIN; i++) { for (j = 0; j < COL; j++) { printf("elemento %d %d = ", i, j); scanf("%d", matriz+(i*col+j)); 42

Solução não muito boa. 43

Resumo da Seção Introdução Declaração Incrementando e Decrementando Ponteiros Ponteiros e Vetores Alocação Dinâmica de Memória Ponteiros e Matrizes Vetores de Ponteiros Ponteiros para ponteiros 44

Um passo em frente 45

Vetores de Ponteiros Uma possibilidade mais interessante é utilizar vetores de ponteiros. Esta não é a notação ideal, mas é um passo na direção da notação mais efetiva. Neste caso cada linha da matriz é apontada por um ponteiro armazenado no vetor de ponteiros. 46

Vetores de Ponteiros #define LIN 10 #define COL 60 int main(void) { char *l[lin]; int i; for (i = 0; i < LIN; i++) { if (!(l[i] = malloc(col*sizeof(char)))) { printf("sem memória %d.\n", i); return i; for (i = 0; i < LIN; i++) { printf("linha %d?\n", i); gets(l[i]); for (i = 0; i < LIN; i++) { printf("linha %d %s.\n", i, lin[i]); return 0; 47

Resumo da Seção Introdução Declaração Incrementando e Decrementando Ponteiros Ponteiros e Vetores Alocação Dinâmica de Memória Ponteiros e Matrizes Vetores de Ponteiros Ponteiros para ponteiros 48

Ponteiros para ponteiros No exemplo anterior o número de linhas da matriz é fixa. Há uma mistura de notação de ponteiros com matrizes. Vamos considerar um exemplo onde tanto o número de linhas como o de colunas é desconhecido. Agora vamos criar um vetor de ponteiros que irá armazenar o endereço inicial de cada linha. 49

Vetores de Ponteiros: Passo 1 Definindo um ponteiro para ponteiro: matriz. int main (void ) { / ponteiro para os ponteiros / int matriz; return 0; **matriz 50

Vetores de Ponteiros: Passo 2 Criando um vetor de ponteiros. Precisamos saber o número de linhas. Cada linha é um vetor. int main (void ) { int matriz; int lin, col; scanf( %d, &lin) ; matriz=(int )malloc(lin sizeof ( int )) ; if (!matriz) { puts( Nao há espaço. ) ; return 1; return 0; 51

Vetores de Ponteiros: Passo 2 **matriz Vetor de ponteiros 0 1 2 lin-1 52

Vetores de Ponteiros: Passo 3 Precisamos saber quantas colunas cada linha vai ter. Cada linha pode ter um tamanho diferente. int main (void) { int **matriz; int lin, col, i, j; /*... */ puts("qual o numero de colunas?"); scanf("%d", &col); for (i=0; i<lin; i++) { *(matriz +i) = (int *) malloc(col*sizeof1(int)); if (! *(matriz+i) ) { printf("sem espaço para linha %d", i); return 1; /*... */ 53

Vetores de Ponteiros: Passo 3 **matriz Vetor de ponteiros *(matriz+0) *(matriz+1) *(matriz+2) linha 0 linha 1 linha 2 *(matriz+n) linha n 54

Ponteiros para ponteiros **matriz Vetor de ponteiros *(matriz+0) *(matriz+1) *(matriz+2) linha 0 linha 1 linha 2 *(matriz+n) linha n 55

The End 56