Estruturas de Dados Heterogêneas
Módulo 1: Ponteiros e Memória
Introdução a Ponteiros e Memória
Ponteiros são variáveis que armazenam endereços de memória, permitindo um acesso
mais eficiente e flexível aos dados. Em C, a memória do programa é organizada em
segmentos: Text, Data, Stack e Heap, cada um com funções específicas.
A alocação de memória pode ser feita de três maneiras:
● Estática: O espaço de memória é reservado na compilação e permanece alocado
durante toda a execução do programa.
● Automática: O espaço é alocado temporariamente dentro de funções e liberado
automaticamente ao término da execução da função.
● Dinâmica: A alocação ocorre em tempo de execução, permitindo maior flexibilidade
no gerenciamento da memória.
Além disso, o uso de ponteiros facilita a manipulação de estruturas de dados complexas,
como arrays, structs e listas encadeadas.
1. Definição de Ponteiro
Um ponteiro é uma variável que armazena um endereço de memória. Ele permite que o
programa acesse e manipule dados indiretamente, proporcionando eficiência e flexibilidade
no gerenciamento de memória.
Principais Características:
● Armazena um endereço de memória ao invés de um valor direto.
● Permite acessar e modificar variáveis indiretamente, o que possibilita a criação
de funções mais genéricas e reutilizáveis.
● Facilita a alocação dinâmica de memória, possibilitando estruturas de dados
dinâmicas.
● É fundamental para manipulação de arrays e strings em C, já que esses
elementos são tratados como ponteiros para a memória alocada.
Para entender ponteiros, é essencial compreender a organização da memória de um
programa.
2. Organização da Memória
É um componente do computador responsável pelo armazenamento de dados e instruções.
A memória do computador é composta por palavras, cada uma com um endereço
exclusivo. Cada palavra tem uma capacidade de armazenamento da informação, isto é,
uma quantidade de bytes que a palavra representa. Em um programa em execução, a
memória é dividida em segmentos lógicos:
Segmentos da Memória:
1. Text (Código): Contém o código do programa armazenado em memória. Esse
segmento é alocado durante a criação do processo (''exec'') e permanece do mesmo
tamanho durante toda a vida do processo.
2. Data (Dados Estáticos): Armazena variáveis globais e estáticas. Tem tamanho fixo
ao longo da execução do processo.
3. Stack (Pilha de Execução): Contém a pilha de execução, na qual são armazenados
os parâmetros, os endereços de retorno e as variáveis locais de funções. Pode
variar de tamanho durante a execução do processo.
4. Heap (Memória Dinâmica): Espaço para alocação dinâmica de memória durante a
execução do programa. Varia de tamanho durante a vida do processo.
A Stack cresce de cima para baixo, enquanto a Heap cresce de baixo para cima. O
gerenciamento correto da memória é essencial para evitar problemas como vazamento de
memória e acessos inválidos.
3. Alocação de Memória
A alocação de memória refere-se ao processo de reservar espaço na memória do
computador para armazenar variáveis e dados. Existem três tipos principais de alocação de
memória em C:
3.1 Alocação Estática
● A alocação estática ocorre durante a compilação do programa, e a memória
reservada permanece alocada até o término da execução.
● Utilizada para variáveis globais e aquelas declaradas com static.
● Rápida e eficiente, mas não permite realocação de memória em tempo de execução.
● Alocação estática (geralmente aloca em DATA).
Exemplo:
static int a = 10;
3.2 Alocação Automática
● Ocorre na Stack, sendo usada para variáveis locais dentro de funções.
● A memória é liberada automaticamente quando a função termina.
● Boa eficiência, mas as variáveis alocadas não podem ser usadas fora da função.
Exemplo:
void funcao() {
int b = 0; // Variável local, alocada automaticamente
}
3.3 Alocação Dinâmica
A alocação dinâmica ocorre em tempo de execução e permite ao programador reservar e
liberar memória conforme necessário. Essa alocação ocorre na Heap, e a memória deve ser
liberada manualmente para evitar vazamentos.
Tipos de Alocação Dinâmica:
● Alocação Dinâmica Manual:
○ O programador tem total controle sobre a alocação e liberação da memória.
○ Usa funções como malloc(), calloc(), realloc() e free().
○ Pode levar a vazamentos de memória se a liberação não for feita
corretamente.
● Alocação Dinâmica Semiautomática:
○ Algumas linguagens e sistemas oferecem gerenciamento parcial da memória,
como garbage collectors.
○ Automação da liberação de memória reduz riscos de vazamentos.
Principais Funções de Alocação Dinâmica:
● malloc(size_t size): Aloca um determinado número de bytes na Heap.
● calloc(size_t count, size_t eltSize): Aloca múltiplos blocos de memória
e os inicializa com zero.
● realloc(void *ptr, size_t size): Redimensiona um bloco de memória
previamente alocado.
● free(void *ptr): Libera a memória previamente alocada.
Exemplo de Uso:
int *ptr = (int*) malloc(sizeof(int));
*ptr = 10; // Armazena o valor 10 no espaço alocado
free(ptr); // Libera a memória alocada
É essencial sempre liberar a memória alocada dinamicamente para evitar vazamentos.
Aqui está o conteúdo reorganizado em tópicos, com explicações claras e mantendo todos
os pontos importantes:
Ponteiros em C
Os ponteiros são variáveis especiais que armazenam endereços de memória. Eles
permitem acessar e modificar valores indiretamente, sem utilizar diretamente o nome da
variável.
1. Introdução aos Ponteiros
Toda variável em C possui:
● Nome: Identificador da variável.
● Tipo: Tipo de dado armazenado (ex: int, char, float).
● Valor: Informação armazenada na variável.
● Endereço: Localização da variável na memória.
Os ponteiros armazenam o endereço de outra variável, permitindo manipulação indireta.
Exemplo:
int x = 5; // variável inteira
char c = 'D'; // variável caractere
● x está armazenado no endereço 10 e ocupa 2 bytes.
● c está armazenado no endereço 13 e ocupa 1 byte.
2. Declaração de Ponteiros
Os ponteiros são declarados utilizando o símbolo * antes do nome da variável:
Tipo_da_Variável *Nome_do_Ponteiro;
Exemplos:
int *p; // Ponteiro para um inteiro
float *q; // Ponteiro para um float
char *r; // Ponteiro para um caractere
3. Operadores de Ponteiros
3.1 Operador & (endereço de memória)
Retorna o endereço de memória de uma variável.
int x = 5;
int *pt_x;
pt_x = &x; // pt_x recebe o endereço de x
Agora pt_x armazena o endereço da variável x.
3.2 Operador * (indireção ou desreferência)
Acessa o conteúdo armazenado no endereço do ponteiro.
*pt_x = 50; // Altera o valor de x para 50
Isso muda x sem precisar referenciá-lo diretamente.
4. Indireção Múltipla (Ponteiro para Ponteiro)
Ponteiros podem armazenar endereços de outros ponteiros, criando níveis de indireção.
4.1 Declaração de um Ponteiro para Ponteiro
int **pt2; // Ponteiro para ponteiro do tipo inteiro
int *pt1; // Ponteiro para inteiro
int x = 10;
pt2 = &pt1; // pt2 armazena o endereço de pt1
pt1 = &x; // pt1 armazena o endereço de x
*pt1 = 30; // x passa a valer 30
**pt2 = 50; // x passa a valer 50
Explicação:
● &pt2: Endereço do ponteiro pt2.
● &pt1: Endereço do ponteiro pt1.
● pt2: Aponta para pt1.
● pt1: Aponta para x.
● *pt2: Conteúdo de pt1.
● **pt2: Conteúdo de x (acesso indireto).
5. Aritmética de Ponteiros
Os ponteiros suportam apenas adição e subtração, desde que os tipos sejam compatíveis.
5.1 Incremento e Decremento
pt++; // Avança para o próximo elemento do tipo do ponteiro
pt--; // Retrocede para o elemento anterior
Se pt for um ponteiro para int (que ocupa 4 bytes), pt++ desloca 4 bytes.
5.2 Exemplo
/* 4 x sizeof(int) = 16 bytes */
pt = pt + 4; // Avança 16 bytes (4 inteiros)
6. Aplicações de Ponteiros
Os ponteiros são amplamente utilizados para:
✔ Alocação dinâmica de memória.
✔ Manipulação eficiente de arrays.
✔ Retornar múltiplos valores em funções.
✔ Referenciar estruturas de dados complexas (listas, pilhas, árvores, grafos).
7. Exemplo Completo de Uso de Ponteiros
#include <stdio.h>
#include <conio.h>
int main(void) {
int v_num = 10; // Variável a ser apontada pelo ponteiro
int *ptr; // Declaração do ponteiro
ptr = &v_num; // Atribuindo o endereço da variável v_num ao ponteiro
printf("Utilizando ponteiros\n\n");
printf("Conteudo da variavel v_num: %d\n", v_num);
printf("Endereco da variavel v_num: %x \n", &v_num);
printf("Conteudo do ponteiro ptr: %x", ptr);
getch();
return 0;
Saída do Programa
Utilizando ponteiros
Conteudo da variavel v_num: 10
Endereco da variavel v_num: 61FE14
Conteudo do ponteiro ptr: 61FE14
Explicação:
● v_num tem valor 10.
● &v_num exibe o endereço de memória da variável.
● ptr armazena esse endereço.
😊
Essa estrutura organizada facilita o entendimento dos conceitos fundamentais de ponteiros
em C.