Docsity
Docsity

Prepare-se para as provas
Prepare-se para as provas

Estude fácil! Tem muito documento disponível na Docsity


Ganhe pontos para baixar
Ganhe pontos para baixar

Ganhe pontos ajudando outros esrudantes ou compre um plano Premium


Guias e Dicas
Guias e Dicas


Curso Linguagem Programação em "C", Notas de aula de Linguagem de Programação

Curso completo de linguagem de programação em C da Uninter

Tipologia: Notas de aula

2020

Compartilhado em 11/08/2020

marcelino-gomes-neto-6
marcelino-gomes-neto-6 🇧🇷

4 documentos

1 / 21

Toggle sidebar

Esta página não é visível na pré-visualização

Não perca as partes importantes!

bg1
LINGUAGEM DE
PROGRAMAÇÃO
AULA 2
Prof. Sandro de Araujo
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14
pf15

Pré-visualização parcial do texto

Baixe Curso Linguagem Programação em "C" e outras Notas de aula em PDF para Linguagem de Programação, somente na Docsity!

LINGUAGEM DE

PROGRAMAÇÃO

AULA 2

Prof. Sandro de Araujo

CONVERSA INICIAL

Esta aula tem como base os livros Fundamentos da Programação de Computadores: Algoritmos , Pascal , C/C++ e Treinamento em Linguagem C. Em caso de dúvidas ou para aprofundamento, consulte-os em nossa Biblioteca Virtual Pearson. A aula apresenta a seguinte estrutura de conteúdo:

  1. Endereços de memória;
  2. Ponteiros;
  3. Ponteiros – tamanho e endereçamento;
  4. Ponteiros e vetores;
  5. Passagem de parâmetros por referência. O objetivo desta aula é conhecer o conceito de ponteiro e sua aplicação em algoritmos computacionais; entender como um dado é acessado na memória; e sua relação com vetores e funções.

TEMA 1 – ENDEREÇOS DE MEMÓRIA

A memória de um computador é dividida em bytes , numerados de zero até o limite de memória da máquina. Esses números são chamados endereços de bytes , usados como referências, pelo computador, para localizar as variáveis (Mizrahi, 2008). Toda variável tem uma localização na memória, e o endereço de identificação desta variável é o primeiro byte ocupado por ela, conforme explicado anteriormente. Se o programa contém a informação somente do endereço do primeiro byte da variável, como ele sabe quais endereços deve ler? Bom, para obter esta resposta, o programa deve saber que toda variável está armazenada em bytes sequenciais e, identificando o tamanho desta variável pelo seu tipo, infere até onde a leitura dos endereços deve ir. Por exemplo, uma variável do tipo int em C com tamanho 4 bytes, ou seja, sabendo o endereço inicial, sabe que, a partir, dele temos mais três endereços sequenciais que correspondem à variável desejada. Quando o programa é carregado na memória, ocupa certa quantidade de bytes , e toda variável e função desse programa terão seu espaço e endereço

operador “ ***** ” antes da variável e o operador “ & ”^1 na chamada do parâmetro (Mizrahi, 2008). O resultado do operador &, "endereço de", sempre será o endereço de memória do elemento em questão, normalmente é o local onde uma variável está alocada na memória. Isto é, esse operador gera um ponteiro. A função scanf() espera que o usuário digite algum dado de entrada e o operador ‘ & ’, acompanhado da variável, serve para especificar o lugar certo onde esse dado vai ficar posicionado na memória. Portanto, o uso do operador de endereço para essa função se faz necessário (Ascencio, 2012). O operador oposto é o * (asterisco), que pega o valor apontado pelo endereço. No exemplo do algoritmo da Figura 1, foram declaradas três variáveis inteiras. Obtivemos como saída a impressão dos seus endereços em hexadecimal com o uso do operador &. O endereço alocado depende de vários fatores, dentre eles, o tamanho da palavra^2 , se há ou não outros programas usando a memória, entre outros. Por essas razões, podemos encontrar endereços diferentes na passagem de parâmetros e execução do algoritmo (Mizrahi, 2008) para cada nova execução de um problema. Faça o teste você mesmo. Implemente o exemplo anterior no seu compilador e mande-o executar diversas vezes. Cada nova execução gerará valores diferentes de endereços alocados. Mizrahi (2008) descreve memória como uma unidade organizada logicamente em palavras. Uma palavra é uma unidade lógica de informação constituída por um número de bits de único endereço, consequentemente, um conjunto de palavras armazenadas na memória é um programa, e pode ser dividido em duas categorias:  Instruções – operações (programa propriamente dito) realizadas pela máquina;  Dados – variáveis, ou valores, processadas nessas operações. Cada palavra é identificada por meio de um endereço de memória sem ambiguidade. Observe a Tabela 1. (^1) O operador unário & retorna o endereço na memória de seu operando (Mizrahi, 2008). (^2) Unidade de informação para cada tipo de computador (Mizrahi, 2008).

Tabela 1 – Exemplo de endereços de palavras Ordem na memória Endereço na memória Palavras 0 000 Palavra 0 1 001 Palavra 1 2 010 Palavra 2 3 011 Palavra 3 4 100 Palavra 4 5 101 Palavra 5 6 110 Palavra 6 7 111 Palavra 7 A capacidade, ou tamanho, de uma memória vai depender do número de palavras que ela pode suportar. A posição de uma palavra dentro da memória é tida como o seu endereço. A primeira palavra da memória tem o endereço 000, a próxima, 001, e assim por diante (Mizrahi, 2008).

TEMA 2 – PONTEIROS

O ponteiro é uma ferramenta poderosa oferecida em linguagens de programação e considerada, pela maioria dos programadores, um dos tópicos mais difíceis (Mizrahi, 2008; Ascencio, 2012). Apontadores, ou ponteiros, são variáveis que armazenam o endereço de outras variáveis na memória. Ou seja, em vez de termos um valor numérico ou caracteres, por exemplo, armazenado na variável, temos um endereço. Dizemos que um ponteiro “aponta” para uma variável na memória quando este contém o endereço daquela variável. O uso de ponteiros é muito útil quando um dado deve ser acessado na memória em diferentes partes de um programa. Assim, podem existir vários ponteiros espalhados, indicando a localidade da variável que contém o dado desejado. Caso este dado seja atualizado, todas as partes que apontam para a variável serão atualizados simultaneamente (Ascencio, 2012). De acordo com Mizrahi (2008), estas são algumas razões para o uso de ponteiros:

  1. Fornecem maneiras com as quais as funções podem realmente modificar os argumentos que recebem (passagem de parâmetros por referência);
  2. Criar estruturas de dados complexas, como listas encadeadas e árvores binárias, em que um item deve conter referências a outro;
  3. Alocar e desalocar memória dinamicamente do sistema;
  4. Passar para uma função o endereço de outra função.

A Figura 4 mostra a saída do algoritmo acima após a sua execução. Figura 4 – Saída do algoritmo Figura 5 – Exemplo de ponteiros A Figura 6 mostra a saída do algoritmo acima após a sua execução. Figura 6 – Saída do algoritmo

Figura 7 – Exemplo de ponteiros A Figura 8 mostra a saída do algoritmo acima após a sua execução. Figura 8 – Saída do algoritmo

TEMA 3 – PONTEIROS: TAMANHO E ENDEREÇAMENTO

Um ponteiro também é uma variável e também ocupa espaço na memória. Normalmente, o tamanho de um ponteiro independe do tipo de dados da variável da qual está apontando e ocupa o espaço de um inteiro (Mizrahi, 2008). Para obter o tamanho de um tipo de variável na linguagem de programação C, utiliza-se a função sizeof. A Figura 9 mostra um algoritmo que imprime o tamanho das variáveis mais usadas na escrita de um programa em linguagem de programação C (Mizrahi, 2008; Ascencio, 2012).

Trabalha-se com ponteiros quando existe a necessidade de ter os valores das variáveis alterados diretamente na memória mostra um. A Figura 12 mostra um algoritmo que evidencia esse conceito. Figura 12 – Manipulação de dados com ponteiros A Figura 13 mostra a saída do algoritmo acima após a sua execução. Figura 13 – Saída do algoritmo No momento em que declarou as variáveis c e d , também se fixaram os valores 5 e 3, respectivamente. Após a execução das instruções, conforme mostrado na Figura 6, seus valores foram alterados para 0 e 8 com o uso de ponteiros.

TEMA 4 – PONTEIROS E VETORES

Vetores unidimensionais, ou arrays , consistem em um conjunto de dados de mesmo tipo armazenados em posições sequenciais na memória, caracterizando uma estrutura de dados homogênea. O nome do vetor é um

ponteiro que aponta para o primeiro elemento do vetor. Observe o algoritmo da Figura 14. Figura 14 – Ponteiros e vetores A Figura 15 mostra a saída do algoritmo acima após a sua execução. Figura 15 – Saída do algoritmo As instruções acima são usadas para criar um ponteiro que vai apontar para o primeiro elemento do vetor x[ ]. A expressão “ pont = x; ” faz com que o ponteiro “ pont ” atribua o endereço do primeiro elemento do vetor x[ ]. A Figura 16 ilustra a atribuição do endereço ao ponteiro “ pont ”. Figura 16 – Representação de um ponteiro com o endereço de um vetor

Figura 18 – Exemplo de ponteiro e vetor A Figura 19 mostra a saída do algoritmo acima após a sua execução. Figura 19 – Saída do algoritmo

Figura 20 – Exemplo de ponteiro e vetor A Figura 21 mostra a saída do algoritmo acima após a sua execução. Figura 21 – Saída do algoritmo

A Figura 25 mostra a saída do algoritmo da Figura 24 após a sua execução. Figura 25 – Saída do algoritmo Para acessar os elementos de pont[0], pont[1], pont[2] e pont[3], basta manipular os ponteiros utilizando o operador ‘*’ e indicar o índice desejado. Conforme mostrado abaixo:  *pont[0] – é o valor 1, o conteúdo do endereço 116, ou seja, x[0] e o mesmo valor pode ser obtido com a instrução  *pont[1] – é o valor 4, o conteúdo do endereço 128, ou seja, y[0];  *pont[2] – é o valor 7, o conteúdo do endereço 140, ou seja, z[0];  *pont[3] – é o valor 10, o conteúdo do endereço 152, ou seja, w[0]. Esse exemplo é ilustrado na Figura 26. Figura 26 – Vetor de ponteiros do tipo inteiro

Figura 27 – Exemplo de vetor de ponteiros A Figura 28 mostra a saída do algoritmo da Figura 27 após a sua execução. Figura 28 – Saída do algoritmo

TEMA 5 – PASSAGEM DE PARÂMETROS POR REFERÊNCIA

Uma das vantagens obtidas com ponteiros é a possibilidade de alterar o valor de variáveis que estão lugares diferentes do programa. O asterisco é utilizado para indicar que as variáveis são ponteiros e guardam o endereço de outras variáveis simples na memória. Portanto, o conteúdo destas variáveis simples também pode ser modificado diretamente na memória quando passados seus endereços por meio

  1. Na linha 13, a instrução soma_mais_1(&a) recebe o endereço da variável ‘ a ’;
  2. Na linha 22, a função soma_mais_1(*num) altera diretamente o dado na memória.
  3. Na linha 15, a função printf() imprime o valor da variável ‘ a ’ depois que a função soma_mais_1(*num) foi executada. Esses efeitos não ocorrem quando os parâmetros são passados por valor (sem o uso do asterisco ‘ ***** ’ e o operador ‘ & ’), em que uma cópia do dado é passada como parâmetro para a função e a variável origem não sofre qualquer alteração. Figura 31 – Exemplo de passagem de parâmetros por referência A Figura 32 mostra a saída do algoritmo acima após a sua execução.

Figura 32 – Saída do algoritmo

FINALIZANDO

Nesta aula, aprendemos os principais conceitos e temas das abordagens sobre ponteiro e sua aplicação em algoritmos computacionais; vimos como um dado é acessado na memória; bem como sua relação com vetores e funções.