Você está na página 1de 31

22/02/2023, 16:54 Técnicas de Programação

TÉCNICAS DE PROGRAMAÇÃO
UNIDADE 3 - ALOCAÇÃ O DE MEMÓ RIA
ESTÁTICA E DINÂ MICA

Fernando Cortez Sica

https://student.ulife.com.br/ContentPlayer/Index?lc=gd%2fd12LVVHhOTw1%2f21SPDQ%3d%3d&l=Cftg%2fqYAWV10o0QR%2fFXMCA%3d%3… 1/31
22/02/2023, 16:54 Técnicas de Programação

https://student.ulife.com.br/ContentPlayer/Index?lc=gd%2fd12LVVHhOTw1%2f21SPDQ%3d%3d&l=Cftg%2fqYAWV10o0QR%2fFXMCA%3d%3… 2/31
22/02/2023, 16:54 Técnicas de Programação

Introdução
Iniciamos o nosso terceiro encontro sobre Técnicas de Programação.  Conversaremos sobre um ponto que
ajudará o programa a se tornar mais flexível e, em certos casos, mais eficiente; essa flexibilidade é conseguida
pela utilização de ponteiros. Mas, já não usamos ponteiros na passagem de parâmetros por referência? Sim,
exato! O primeiro uso e contato com os ponteiros foi na passagem de parâmetros por referência (usando os
símbolos “&” e “*”). Mas, aonde mais usamos ponteiros? Podemos encontrar ponteiros nos có digos que
manipulam os dispositivos do hardware (os chamados device drivers), no kernel do sistema operacional, nos
sistemas de banco de dados e em outras diferentes aplicaçõ es! Quando conversamos sobre vetores e falamos
que seria necessário definirmos um tamanho já na declaração de variáveis, você pode ter se perguntado: mas,
caso a quantidade de itens manipulados aumentasse, teríamos que modificar o programa, alterando-se o
tamanho do vetor? Sim, no caso dos vetores, já que eles são estruturas de tamanho fixo, pré-definido. Mas,
então, com a utilização de ponteiros, esse problema é eliminado? Sim, veremos uma estratégia denominada
alocação de memó ria dinâmica que servirá, dentre outras coisas, para eliminar esse problema.
No entanto, pode surgir uma outra questão: se os ponteiros nos possibilitam uma manipulação de memó ria
mais poderosa, então é mais difícil de programar? Vamos tentar não usar o termo dificuldade e, sim, falar que
o uso de ponteiros requer um pouco mais de atenção devido ao seu alto poder de abstração.
Neste capítulo, falaremos sobre os conceitos e manipulação de ponteiros. Já que mencionamos,
anteriormente, que os vetores na passagem de parâmetros das funçõ es, são considerados como ponteiros,
então veremos como definir vetores e matrizes usando ponteiros; em seguida, conversaremos sobre uma
outra forma de manipular informaçõ es, no caso, informaçõ es heterogêneas: o uso de estruturas ou registros.
Por fim, vamos abordar a representação de tais estruturas como ponteiros.

3.1 Ponteiros 
Um ponteiro é uma referência a uma posição de memó ria. A diferença básica entre uma variável do tipo
ponteiro e uma não ponteiro consiste no fato de que uma variável que não seja ponteiro armazena um valor
propriamente dito. Por sua vez, uma variável do tipo ponteiro, realiza uma indireção, ou seja, faz uma
referência indireta a um valor. Mas, na declaração de uma variável, como diferenciar e manipular os dois
tipos? Para respondermos essa pergunta, vamos nos amparar com o có digo abaixo: 

https://student.ulife.com.br/ContentPlayer/Index?lc=gd%2fd12LVVHhOTw1%2f21SPDQ%3d%3d&l=Cftg%2fqYAWV10o0QR%2fFXMCA%3d%3… 3/31
22/02/2023, 16:54 Técnicas de Programação

Neste có digo, temos as explanaçõ es para as linhas descritas a seguir. Clique nos itens e confira!

Linha 1
Declaraçã o da variável “a” do tipo “int” (sem ser
ponteiro), instanciada com o valor 10.

Linha 2
Declaraçã o da variável “b” como sendo um
ponteiro para um “int”. Para declarar um
ponteiro, utiliza-se “*” antes do nome da variável
(como denotado por “*b”).

Linha 3
Nesta linha temos a indicaçã o que a posiçã o de
memó ria apontada por “b” passa a ser o endereço
da variável “a”. O ponteiro “b”, neste caso, nã o fez
uso do “*” o precedendo, pois, estamos a
manipular o pró prio valor do ponteiro. Para
denotarmos a posiçã o de memó ria de uma

https://student.ulife.com.br/ContentPlayer/Index?lc=gd%2fd12LVVHhOTw1%2f21SPDQ%3d%3d&l=Cftg%2fqYAWV10o0QR%2fFXMCA%3d%3… 4/31
22/02/2023, 16:54 Técnicas de Programação

variável usamos o símbolo “&” (como denotado


por “&a”). Você pode se perguntar: é por esse
motivo que usamos esse símbolo “&” na
passagem de parâ metros por referência nas
funçõ es? Sim, exatamente. Na chamada da funçã o,
os parâ metros passados por referência sã o
precedidos por “&” pois passamos para a funçã o,
na verdade, o endereço de memó ria da variável
envolvida.

Linha 4
A funçã o “printf” imprime os valores da variável
“a” e do conteú do da posiçã o de memó ria
apontado por “b” e, também, a posiçã o de
memó ria na qual foi alocada a variável “a” e a
posiçã o do ponteiro “b”. Na execuçã o, poderemos
notar que esses dois ú ltimos valores sã o iguais
pois referenciam a mesma posiçã o de memó ria.

Linha 5
O valor da variável “a” é modificada. Como o
ponteiro “b” aponta para “a”, qualquer
modificaçã o de “a” altera prontamente, o valor do
conteú do de “b”. Sendo assim, a funçã o “printf” da
linha 6 imprimirá o valor atribuído a “a”; no caso,
imprimirá o valor 30.
O fato da modificação da variável “a” impactar o valor do conteú do apontado pela variável “b”, apó s a execução
da linha  3, pode ser explicado por intermédio da figura a seguir:

https://student.ulife.com.br/ContentPlayer/Index?lc=gd%2fd12LVVHhOTw1%2f21SPDQ%3d%3d&l=Cftg%2fqYAWV10o0QR%2fFXMCA%3d%3… 5/31
22/02/2023, 16:54 Técnicas de Programação

Figura 1 - Estados das variáveis apó s a execução da linha 5 do có digo acima. O ponteiro “b” aponta para a
mesma posição de memó ria da variável “a”.
Fonte: Elaborada pelo autor, 2019.

A figura acima ilustra que apó s a execução da linha contendo a instanciação “b = &a”, o ponteiro “b” aponta
para a mesma posição de memó ria da variável “a”. Sendo assim, qualquer alteração de “a” altera o conteú do do
ponteiro “b” (“*b”).
Como mencionado em Deitel (2011), todo ponteiro, para ser efetivamente manipulado, deve ser instanciado.
Porém, podemos, em algumas ocasiõ es, definir um ponteiro apontando para um valor nulo. Neste caso, para
criarmos um ponteiro nulo poderemos proceder de alguma das formas a seguir:

Na linha de có digo acima, temos a instanciação de dois ponteiros    com o valor nulo. A
definição do “ ” encontra-se no arquivo header “ ”.
Falamos até aqui, de um ponteiro apontando para uma variável não ponteiro. Mas, um ponteiro também pode
apontar para um ponteiro? Veremos isso a seguir.

3.2 Ponteiros para ponteiros


Um ponteiro para ponteiro significa que a variável do tipo ponteiro não faz referência a uma posição de
memó ria e, sim, faz referência à um outro ponteiro. Esse ú ltimo, por sua vez, aponta uma posição de memó ria
que contém, efetivamente, o valor armazenado. Para falarmos de ponteiros para ponteiros, vamos imaginar
uma utilidade: suponha que uma matriz seja implementada com ponteiros (como veremos adiante); e que, em
um certo momento, necessitemos realizar uma operação de ordenação, sabemos que a ordenação da matriz
necessita da movimentação de dados. Uma ú ltima suposição: cada célula da matriz armazena uma informação
de tamanho relativamente grande. Com esse cenário, podemos concluir que demandaremos para realizar a
operação de ordenação, uma grande movimentação de informaçõ es. Para atenuar isso, podemos construir
uma matriz formada por ponteiros para ponteiros. Neste caso, cada ponteiro aponta para uma posição da
matriz, ou seja, um ponteiro aponta para cada ponteiro que caracteriza a matriz. Sendo assim, ordenar uma
matriz, significa instanciar ponteiros e não movimentar grandes volumes de informação. (MIZRAHI, 2008).
Mas, como podemos definir ponteiros para ponteiros? Vamos analisar o có digo a seguir:

https://student.ulife.com.br/ContentPlayer/Index?lc=gd%2fd12LVVHhOTw1%2f21SPDQ%3d%3d&l=Cftg%2fqYAWV10o0QR%2fFXMCA%3d%3… 6/31
22/02/2023, 16:54 Técnicas de Programação

Clique nas abas abaixo e conheça a descrição de cada linha do có digo acima.

Linha 1

 A variável “ b ” é um ponteiro para “ int ” (uso do símbolo “ * ” precedendo o nome da variável).


Por sua vez, o uso de dois sinais “ * ” denota, em “ c ” um ponteiro para ponteiro.

Linha 2

Instanciação do ponteiro “ b ” recebendo o endereço da variável “ a ”.

Linha 3

instanciação do ponteiro para ponteiro “ c ” recebendo o endereço do ponteiro “ b ”.

Linha 4 e 5

Impressão dos conteúdos e dos endereços das variáveis e ponteiros. Nota-se que, para imprimir o valor
final (no caso 10), devemos indicar, no caso do ponteiro para ponteiro “ c ” que a impressão se refere
ao conteúdo do conteúdo de “ c ”, ou seja, valor do ponteiro que aponta para o ponteiro “ b ” que,
por sua vez, aponta para a variável “ a ” – esse é o motivo da utilização de “**” precedendo o nome da
variável.

A figura a seguir ilustra melhor esse encadeamento de indireçõ es.

https://student.ulife.com.br/ContentPlayer/Index?lc=gd%2fd12LVVHhOTw1%2f21SPDQ%3d%3d&l=Cftg%2fqYAWV10o0QR%2fFXMCA%3d%3… 7/31
22/02/2023, 16:54 Técnicas de Programação

Figura 2 - Relação dos apontamentos feitos por um ponteiro (“*b”) e por um ponteiro para ponteiro (“**c”).
Fonte: Elaborada pelo autor, 2019.

Em C, podemos aumentar a indireção criando, por exemplo, ponteiro para ponteiro para ponteiro. Neste caso,
a criação da variável seria feita da seguinte forma, por exemplo: “int ***p”. A quantidade de símbolos “*”
indica a quantidade de indireçõ es desejadas.

VOCÊ SABIA?
Em algumas ocasiões, tais como sistemas embarcados, funções para o tratamento
de interrupções e implementaçã o de “threads”, temos que usar ponteiros para
funções. Desta forma, a chamada de funções torna-se dinâ mica, facilmente
configurável. Para saber um pouco mais sobre o assunto, clique neste link
<https://www.embarcados.com.br/ponteiro-em-c-funcoes/
(https://www.embarcados.com.br/ponteiro-em-c-funcoes/)>. (GARCIA, 2015). 

Quando mencionamos uma das aplicaçõ es de ponteiros para ponteiros, mencionamos o caso de matrizes
definidas com ponteiros. Para chegar lá, vamos compreender antes, como definimos vetores com ponteiros.

3.3 Alocação de vetores como ponteiros


Quando mencionamos o fato de que na passagem de parâmetros de funçõ es, os vetores se comportam como
passagem por referência, queremos dizer que, na verdade, vetores são manipulados como ponteiros. De fato, o
compilador cria um espaço de memó ria de tamanho N*K, onde N representa a dimensão do vetor e K o espaço

https://student.ulife.com.br/ContentPlayer/Index?lc=gd%2fd12LVVHhOTw1%2f21SPDQ%3d%3d&l=Cftg%2fqYAWV10o0QR%2fFXMCA%3d%3… 8/31
22/02/2023, 16:54 Técnicas de Programação

gasto para armazenar um item de um determinado tipo de dado. Então, podemos definir um vetor como
ponteiros da seguinte forma:

Mas, como inserir e ler os valores contidos em um vetor declarado desta forma? Para que possamos entrar
neste assunto, veremos o exemplo de codificação a seguir:

Para conhecer a descrição do có digo apresentado, clique nas abas abaixo. 

Linha 1 Criação e instanciação do vetor “vet” de valores inteiros de 10 posiçõ es.

Criação de uma variável do tipo ponteiro para inteiro “pvet” (linha 2) e a sua
instanciação (na linha 3), recebendo o endereço ocupado pelo vetor “vet”. Nota-se
que, nesta linha, não aparece o símbolo “&” precedendo a variável “vet” pois ela,
Linha 2 e
sendo um vetor, já é considerada como um ponteiro. Sendo assim, a partir deste
3
momento, a variável “pvet” aponta para o início do vetor “vet”. Essa instanciação
poderia ser feita, também, da seguinte forma: “pvet = &vet[0]” – o ponteiro “pvet”
recebe o endereço da posição 0 do vetor “vet”.

Instanciação de uma posição do vetor. O có digo “*(pvet + 3) = 13” pode ser traduzido
Linha 4 para a seguinte forma: o conteú do do vetor cuja posição é o início do vetor deslocada
de 3 itens recebe o valor 13. 

https://student.ulife.com.br/ContentPlayer/Index?lc=gd%2fd12LVVHhOTw1%2f21SPDQ%3d%3d&l=Cftg%2fqYAWV10o0QR%2fFXMCA%3d%3… 9/31
22/02/2023, 16:54 Técnicas de Programação

O mesmo processo de acessar a posição 5 a partir do início do vetor para que seja
Linha 5 instanciada com o valor 15. Essa mesma interpretação deve ser feita na linha 7, para
proceder a impressão do conteú do do vetor.

O processo de acessar uma posição N a partir do início do vetor é ilustrada na figura a seguir:

Figura 3 - Acessando a posição 3 de um vetor através do uso de ponteiro. O valor 3 representa o


deslocamento (offset) a partir do início do vetor.
Fonte: Elaborada pelo autor, 2019.

Como ilustrado na figura acima, o índice utilizado para o acesso à uma posição específica (no caso, utilizado
como exemplo, o valor 3), representa o deslocamento a partir da posição inicial do vetor. Mas, quantos bytes
representa esse deslocamento? A quantidade de bytes saltada por unidade de índice varia em função do
tamanho do item representado. Para saber o tamanho de um tipo, pode-se utilizar a função “sizeof(<tipo>)” da
seguinte forma:

Na linha acima, a função “sizeof” retornará um valor inteiro que representa a quantidade de bytes utilizada por
um “int”. Voltando ao deslocamento, você pode se perguntar: se eu posso adicionar um valor à um ponteiro eu
obtenho uma posição específica de memó ria, então, eu posso incrementar um ponteiro? Sim, é possível
realizar incrementaçõ es com ponteiros. Por exemplo, caso façamos, “p++” (sendo “p” um ponteiro), significa
que “p” apontará para a pró xima posição deslocados N bytes (sendo que N denota o tamanho ocupado pelo
tipo manipulado). Para testar esse comportamento, tomaremos como exemplo, o trecho a seguir:

https://student.ulife.com.br/ContentPlayer/Index?lc=gd%2fd12LVVHhOTw1%2f21SPDQ%3d%3d&l=Cftg%2fqYAWV10o0QR%2fFXMCA%3d%… 10/31
22/02/2023, 16:54 Técnicas de Programação

Vamos, então, substituir o “*(pvet+i)” por “*(pvet++)”:

Teremos o mesmo resultado. Porém, ao invés de incrementarmos o índice “i”, estamos a mudar o pró prio
ponteiro, fazendo-o apontar para a posição subsequente de memó ria a cada iteração do laço de repetição.
Neste caso, para que voltemos à posição inicial do vetor, precisaremos decrementar o ponteiro ou ter salvo,
em outra variável, a referência de memó ria relativa à posição 0. Até o momento, usamos ponteiros apenas
para referenciar vetores criados estaticamente, ou seja, referenciar vetores criados através do có digo: “<tipo>
nome[dimensão]”. Seria possível criar um vetor dinamicamente? O que seria alocação dinâmica de memó ria?
Alocação dinâmica consiste em reservar espaços de memó ria sob demanda, ela é ú til para, por exemplo,
quando não se conhece previamente a quantidade de informaçõ es que serão manipuladas, ou ainda, quando é
necessário criar estruturas temporárias de armazenamento na memó ria principal.

https://student.ulife.com.br/ContentPlayer/Index?lc=gd%2fd12LVVHhOTw1%2f21SPDQ%3d%3d&l=Cftg%2fqYAWV10o0QR%2fFXMCA%3d%… 11/31
22/02/2023, 16:54 Técnicas de Programação

VOCÊ QUER VER?


A alocaçã o dinâ mica de memória é realizada em uma regiã o denominada “heap”. O
computador, para gerenciar os programas usa, alé m do “heap”, a pilha (“stack”). O
vídeo postado pelo professor da USP de Sã o Carlos, Rodrigo Mello, mostra a diferença
entre as duas porções de memória. Você pode assisti-lo neste link
<https://www.youtube.com/watch?v=i_0IBJkXn2M
(https://www.youtube.com/watch?v=i_0IBJkXn2M)>, e aumentar seus conhecimentos
sobre o assunto.

O processo de criação de estruturas dinâmicas (vetores ou registros) é feito por intermédio da função
“malloc” ou “calloc”, para a liberação da memó ria previamente alocada pelo “malloc”, utiliza-se a função “free”
(“malloc” e “free” estão definidas no arquivo header “stdlib.h”). 

https://student.ulife.com.br/ContentPlayer/Index?lc=gd%2fd12LVVHhOTw1%2f21SPDQ%3d%3d&l=Cftg%2fqYAWV10o0QR%2fFXMCA%3d%… 12/31
22/02/2023, 16:54 Técnicas de Programação

VOCÊ O CONHECE?
Uma das primeiras ideias para a alocaçã o dinâ mica de memória surgiu com os
manuscritos de Von Neumann, estudado e publicado em 1970, por Donald Knuth,
atravé s do artigo “Von Neumann´s first Computer Program” (O primeiro programa de
computador do Von Neumann). Para saber um pouco mais sobre a importâ ncia de
Knuth para o mundo dos algoritmos, acesse
<https://internacional.estadao.com.br/noticias/nytiw,conheca-o-cientista-considerado-
o-guia-espiritual-dos-algoritmos,70002654893
(https://internacional.estadao.com.br/noticias/nytiw,conheca-o-cientista-considerado-
o-guia-espiritual-dos-algoritmos,70002654893)>.

Mas, como utilizar as funçõ es “malloc” e “free”?  Para responder a esta pergunta, vamos analisar antes as suas
sintaxes para depois, darmos uma olhada na sua forma de uso.
void * malloc(quantidade_de_bytes_a_serem_alocados);
void *calloc(quantidade_de_itens, tamanho_de_um_item);
void *realloc(ponteiro_a_ser_realocado, quantidade_de_bytes);
free(ponteiro_a_ser_desalocado);
A diferença básica entre as funçõ es “malloc()” e “calloc()” consiste no fato de que a “calloc”, além de alocar
espaço da memó ria, o preenche com o valor 0 (zero). Por sua vez, a função “realloc()” tem a função de
realocar um espaço de memó ria. A função retorna um novo ponteiro, cujo tamanho é especificado como
parâmetro.
 Então como utilizar, efetivamente, as funçõ es “malloc”, “calloc”, “realloc” e “free”? Para isso, vejamos o có digo
a seguir:

https://student.ulife.com.br/ContentPlayer/Index?lc=gd%2fd12LVVHhOTw1%2f21SPDQ%3d%3d&l=Cftg%2fqYAWV10o0QR%2fFXMCA%3d%… 13/31
22/02/2023, 16:54 Técnicas de Programação

No trecho de có digo acima, podemos encontrar a utilização de alocação dinâmica para a construção de um
vetor de inteiros (com a dimensão de “NumCelulas”) e uma string de tamanho “TamanhoStr”. Nota-se que
foram utilizadas as funçõ es “malloc()” e “calloc()” para a alocação dinâmica inicial de memó ria. Para realizar
o redimensionamento do vetor, apó s a sua criação, utilizou-se a função “realloc()”, tomando-se por base o
pró prio ponteiro “vetor” para a sua nova instanciação. 

3.4 Alocação de matrizes como ponteiros


Assim como os vetores, as matrizes também podem ser manipuladas através da utilização de ponteiros. O
processo de criação e manipulação é análogo aos vetores, porém, adicionaremos uma dimensão a mais:
vamos lembrar que para a criação de um vetor, são alocados N*K bytes na memó ria, onde N representa a
dimensão do vetor e K o espaço gasto para armazenar um item de um determinado tipo de dado. Por sua vez,
para a criação de uma matriz, são alocados N*M*K bytes, onde N e M representam a dimensão da matriz e K
denota o tamanho de cada item (em função do tipo de dado a ser armazenado).
Desta forma, para acessar um item da matriz, procedemos na forma:

https://student.ulife.com.br/ContentPlayer/Index?lc=gd%2fd12LVVHhOTw1%2f21SPDQ%3d%3d&l=Cftg%2fqYAWV10o0QR%2fFXMCA%3d%… 14/31
22/02/2023, 16:54 Técnicas de Programação

Para entendermos melhor, vamos analisar o có digo a seguir:

No có digo acima, temos as seguintes funcionalidades das linhas marcadas como comentários, clique nos
itens e confira.

Linhas 1 e 2

https://student.ulife.com.br/ContentPlayer/Index?lc=gd%2fd12LVVHhOTw1%2f21SPDQ%3d%3d&l=Cftg%2fqYAWV10o0QR%2fFXMCA%3d%… 15/31
22/02/2023, 16:54 Técnicas de Programação

Definiçõ es de constantes de compilaçã o para


facilitar a parametrizaçã o da matriz; dessa forma,
torna-se mais prá tico quando necessá rio alterar
as dimensõ es da matriz pois nã o se necessita
mudar o có digo no tangente à s dimensõ es da
matriz.

Linha 3
Criaçã o da matriz do tipo “int” com dimensõ es
NLINHAS x NCOLUNAS e a sua respectiva
instanciaçã o.

Linha 4
Criaçã o do ponteiro para inteiro que ficará a
cargo de referenciar a posiçã o de memó ria
alocada para armazenar a matriz. Além disso,
foram instanciadas variáveis que serã o os índices
manipulados pelos laços de repetiçã o.

Linha 6
Instanciaçã o do ponteiro para a matriz
denominada como “matriz”. A referência, neste
caso, é feita através da indicaçã o do início da
linha 0 ou passando o endereço do elemento
“matriz[0][0]”.

Linha 7
Instanciaçã o do elemento “matriz[2][1]”
atribuindo-lhe o valor 13. Nota-se que foi
realizado o cá lculo “linha*NCOLUNAS+coluna”

https://student.ulife.com.br/ContentPlayer/Index?lc=gd%2fd12LVVHhOTw1%2f21SPDQ%3d%3d&l=Cftg%2fqYAWV10o0QR%2fFXMCA%3d%… 16/31
22/02/2023, 16:54 Técnicas de Programação

pelo fato de que uma matriz é transformada em


uma estrutura linear para que seja armazenada
na memó ria principal do dispositivo
computacional. Essa linearizaçã o é realizada por
linha, ou seja, o primeiro elemento da segunda
linha encontra-se apó s todos os elementos da
primeira e assim sucessivamente. Sendo assim, a
cada linha, deve-se saltar NCOLUNAS itens.

Linha 8
Impressã o do conteú do das células da matriz.
Nota-se, também, a mesma operaçã o
“linha*NCOLUNAS+coluna” para o acesso ao
conteú do.
Da mesma forma dos vetores, poderemos alocar as matrizes dinamicamente usando também as funçõ es
“malloc()” ou “calloc()” e liberando o seu espaço com a função “free()” conforme as linhas a seguir:
int *matriz;
matriz = (int *) calloc(num_linhas*num_colunas , sizeof(int));
...
free(matriz);
No trecho de có digo acima temos a criação de forma dinâmica de uma matriz de dimensõ es “num_linhas” por
“num_colunas” (totalizando “num_linhas * num_colunas” células) do tipo “int”.
  Mencionamos, anteriormente, que uma matriz pode ser construída a partir do uso de ponteiros para
ponteiros. Mas como seria isso? Para entender, vamos observar o có digo abaixo:

https://student.ulife.com.br/ContentPlayer/Index?lc=gd%2fd12LVVHhOTw1%2f21SPDQ%3d%3d&l=Cftg%2fqYAWV10o0QR%2fFXMCA%3d%… 17/31
22/02/2023, 16:54 Técnicas de Programação

Neste có digo, temos as linhas numeradas como comentários com algumas funcionalidades; clique nos itens e
confira.

Linha 1
Declaraçã o das variáveis, destacando-se a
variável “matriz” que é do tipo “ponteiro para
ponteiro de inteiro”.

Linha 2 e 3
Na linha 2, ocorre a alocaçã o de espaço de
memó ria para receber um vetor de ponteiros
para ponteiros de tamanho “linha”. Cada “linha”

https://student.ulife.com.br/ContentPlayer/Index?lc=gd%2fd12LVVHhOTw1%2f21SPDQ%3d%3d&l=Cftg%2fqYAWV10o0QR%2fFXMCA%3d%… 18/31
22/02/2023, 16:54 Técnicas de Programação

da matriz, na linha 4 do có digo, recebe o


endereço de um ponteiro que denota um vetor
correspondente à s colunas.

Linha 4
Ocorre a instanciaçã o das células da matriz. Note
que podemos utilizar também, colchetes para
delimitar os índices da matriz. Foi escolhida a
expressã o “i*10+j” para que cada célula contenha
a referência da coordenada correspondente. Por
exemplo, a posiçã o “[3][2]” corresponderá a
“3*10+2”, ou seja, “32”.

Linha 5
Contém o có digo para realizar a impressã o na
tela das células da matriz.
Essa aplicação de mapeamento de matrizes utilizando-se ponteiro para ponteiro é extremamente ú til para a
passagem de parâmetro por referência. No caso, uma matriz poderá ser recebida como “int **matriz”

https://student.ulife.com.br/ContentPlayer/Index?lc=gd%2fd12LVVHhOTw1%2f21SPDQ%3d%3d&l=Cftg%2fqYAWV10o0QR%2fFXMCA%3d%… 19/31
22/02/2023, 16:54 Técnicas de Programação

CASO
Um projetista de software recebeu um projeto de um sistema computacional
para que fosse implementado, fazia parte deste um problema de otimizaçã o para
gerenciar recursos energé ticos, o chamado Smart Grid (Grade Inteligente, na
traduçã o literal). Esses recursos envolvem a parte de geraçã o (por operadores de
energia, geraçã o particular nas residê ncias e indú strias) e distribuiçã o de
energia. No projeto, ele recebeu um nú mero específico de pontos que deveriam
ser alocados em matrizes, o processo de otimizaçã o envolve a manipulaçã o de
forma massiva, de tais matrizes. Ele teve os seguintes pensamentos: será que a
soluçã o dada ao problema poderia ser usada em outras circunstâ ncias? Será que
a quantidade de elementos poderia mudar (para mais ou para menos) em
projetos similares futuros? Será que poderiam ser implementadas matrizes
esparsas ao invé s de matrizes que alocam todos os seus elementos (inclusive os
valores nulos) na memória? Informamos aqui, que somente as cé lulas nã o nulas
de uma matriz esparsa sã o alocadas na memória. Entã o, para resolver esses
questionamentos, o projetista implementou o seu sistema usando alocaçã o
dinâ mica para representar os dados a serem manipulados. Com isso, ele
introduziu em seu sistema, o conceito de escalabilidade, que consiste em criar um
programa que seja fá cil se adequar a outros volumes de dados para o
processamento. Essa adequaçã o deve ser realizada com a menor quantidade
possível de alterações no código do programa.

Até o momento conversamos apenas sobre a manipulação de estruturas para o armazenamento de


informaçõ es do mesmo tipo, ou seja, estruturas homogêneas. Mas, seria possível o armazenamento de
informaçõ es de vários tipos em uma ú nica estrutura? Para isso, existem os registros ou estruturas, que
veremos a seguir.

3.5 Tipos de dados heterogêneos


Algumas vezes, quando implementamos programas é ú til criarmos variáveis que conseguem armazenar
vários itens com tipos diferentes de informaçõ es. Vamos pensar, que devemos manipular informaçõ es de uma
pessoa para depois, por exemplo, salvar em um arquivo; ela pode ter atributos tais como: nome, endereço, dia,
mês e ano de nascimento. Para o processo de gravação ou recuperação do arquivo, neste caso, manipulamos
todas as informaçõ es simultaneamente ao invés de efetuarmos a gravação ou recuperação campo por campo.
(ASCENCIO, 2012). Mas, como declarar variáveis que admitem informaçõ es heterogêneas? É o que veremos
agora.

https://student.ulife.com.br/ContentPlayer/Index?lc=gd%2fd12LVVHhOTw1%2f21SPDQ%3d%3d&l=Cftg%2fqYAWV10o0QR%2fFXMCA%3d%… 20/31
22/02/2023, 16:54 Técnicas de Programação

3.5.1 Declaração de Variáveis do Tipo Registro


Como mencionamos a pouco, existe a possibilidade de criarmos estruturas de dados que conseguem
armazenar, de forma agrupada, informaçõ es heterogêneas. Nomeia-se como dados heterogêneos aqueles
constituídos de informaçõ es que possuem tipos distintos. Na programação em C, esse agrupamento é
conseguido através da utilização de estruturas de dados denominadas como “struct“. Mas, como criar uma
“struct”? Abordaremos quatro formas para a criação de “struct“, na figura a seguir:

Figura 4 - Formas de declaração e instanciação de registros (“struct”). Nota-se que a “struct” é formada por
campos – podendo possuir tipagens distintas.
Fonte: Elaborada pelo autor, 2019.

Temos, na figura acima, em (a), a criação de um novo tipo de dados para representar “struct”. O termo “typedef
struct”, identifica que estamos criando um novo tipo de dados no formato de estrutura, esse novo tipo foi
batizado como “nome_da_struct”. Ele será usado, posteriormente, para a criação de variáveis na forma “<tipo>
nome_da_variável”, como especificado em “<nome_da_struct> var_struct”.
Ainda em relação à figura acima, temos em (b), (c) e (d) outras formas de criação de variáveis do tipo “struct”.
Em todas as formas, temos os dois momentos distintos: a criação da “struct” e depois, a criação das variáveis
que manipularão as informaçõ es heterogêneas.
Para melhor ilustrar, vamos analisar o trecho de có digo abaixo:

https://student.ulife.com.br/ContentPlayer/Index?lc=gd%2fd12LVVHhOTw1%2f21SPDQ%3d%3d&l=Cftg%2fqYAWV10o0QR%2fFXMCA%3d%… 21/31
22/02/2023, 16:54 Técnicas de Programação

No có digo acima, temos entre as linhas 1 e 5, a criação de um novo tipo de dado do tipo “struct” batizado
como “PESSOA” (linha 5). Os campos que compõ em a estrutura integram as linhas 2 a 4.  A declaração de uma
variável do tipo “PESSOA”, intitulada “p” é realizada na linha 6.
Uma outra forma de se declarar um registro utilizando-se a forma indicada por (b) na figura anterior, seria:

Nota-se, no exemplo de có digo acima, como não foi criado um novo tipo de dado (ausência do “typedef”),
houve a necessidade da utilização de “struct” antes do tipo “PESSOA” para a criação da variável “p”.

https://student.ulife.com.br/ContentPlayer/Index?lc=gd%2fd12LVVHhOTw1%2f21SPDQ%3d%3d&l=Cftg%2fqYAWV10o0QR%2fFXMCA%3d%… 22/31
22/02/2023, 16:54 Técnicas de Programação

VOCÊ QUER LER?


Nas estruturas, podemos definir os tamanhos dos campos (em bits), desta forma, é
possível criar os chamados campos de bits; estes sã o utilizados, sobretudo, na
manipulaçã o de sistemas em baixo nível, como por exemplo, para a escrita de device
drivers, sistemas embarcados e kernel de sistemas operacionais. Para saber mais sobre
o assunto, acesse este link <https://docs.microsoft.com/pt-br/cpp/c-language/c-bit-
fields?view=vs-2019 (https://docs.microsoft.com/pt-br/cpp/c-language/c-bit-fields?
view=vs-2019)>.

Até o momento, realizamos a criação de variáveis do tipo “struct”. Mas como manipulá-las? Como acessar e
instanciar os seus campos? Veremos a manipulação de variáveis do tipo “struct” a seguir.

3.5.2 Acesso aos membros de um registro


O acesso ao campo se faz de forma igual, tanto para a instanciação quanto para a coleta dos valores de uma
variável do tipo “struct”; mencionando o nome da variável e o nome do membro da estrutura a ser acessada
(esses dois itens separados por um ponto): variável.membro.
Para ilustrar melhor, convido-o para analisar o có digo a seguir:

https://student.ulife.com.br/ContentPlayer/Index?lc=gd%2fd12LVVHhOTw1%2f21SPDQ%3d%3d&l=Cftg%2fqYAWV10o0QR%2fFXMCA%3d%… 23/31
22/02/2023, 16:54 Técnicas de Programação

Como já mencionamos, as linhas 1 a 5 do có digo acima visam a definição da “struct” intitulada como
“PESSOA”, enquanto a linha 6 realiza a criação da variável “p” do tipo “PESSOA”. O acesso aos seus campos
podem ser observados nas linhas de 7 a 10. Nota-se o formato “var.campo” na manipulação dos campos da
estrutura. 

https://student.ulife.com.br/ContentPlayer/Index?lc=gd%2fd12LVVHhOTw1%2f21SPDQ%3d%3d&l=Cftg%2fqYAWV10o0QR%2fFXMCA%3d%… 24/31
22/02/2023, 16:54 Técnicas de Programação

VOCÊ QUER VER?


Uma forma de estruturar e encapsular informações heterogê neas é a base da
programaçã o orientada por objetos. Orientaçã o por objeto é a base de muitos sistemas
atuais, escritos por exemplo, em C++ e em Java.

Acesse este vídeo <https://www.youtube.com/watch?v=fyvhl_EostE


(https://www.youtube.com/watch?v=fyvhl_EostE)>, para conhecer mais dos conceitos
deste paradigma de programaçã o (https://www.youtube.com/watch?v=fyvhl_EostE).

Além de facilitar o processo de manipulação de arquivos, a utilização de estruturas deixa o có digo mais
organizado, aumenta o fator de abstração pelos desenvolvedores e, dentre outras vantagens, facilita a
implementação quando desejamos passar informaçõ es para outros mó dulos/funçõ es do programa.
Mas, já que mencionamos ponteiros anteriormente, estruturas podem ser mapeadas como ponteiros? A
resposta a essa pergunta veremos adiante.

3.6 Ponteiros como Registros


Uma questão que poderá ser levantada agora reside no fato de como usar as “struct” como ponteiros? Essa é
uma informação importante pois poderemos usá-la inicialmente, em dois momentos: um relativo à passagem
de parâmetro por referência nas funçõ es e o outro que consiste em alocação dinâmica.
Para o primeiro momento, vamos manipular uma “struct” como um ponteiro alocado estaticamente, na forma:

https://student.ulife.com.br/ContentPlayer/Index?lc=gd%2fd12LVVHhOTw1%2f21SPDQ%3d%3d&l=Cftg%2fqYAWV10o0QR%2fFXMCA%3d%… 25/31
22/02/2023, 16:54 Técnicas de Programação

No có digo acima, podemos visualizar que o ponteiro para o tipo “PESSOA”, intitulado como “pPessoa”, recebeu
a posição de memó ria alocada para a variável “Pessoa” (pPessoa = &Pessoa). Porém, o acesso ao campo tem
uma alteração de sintaxe em relação ao acesso de campos de “struct” que não sejam ponteiro. Nesse momento,
o acesso se dará na forma: “var->campo” ou “(*var).campo”. Sendo assim, no trecho de có digo acima, para o
caso desejarmos instanciar o campo “dia” do ponteiro “pPessoa”, teremos que fazer, por exemplo:
       (*pPessoa).dia = 5;             //1
scanf(“%d”,&pPessoa->mes);  //2
Nas linhas acima, temos em “1”, a instanciação direta do campo “dia” do ponteiro “pPessoa”. Já, na linha 2, o
campo “mes” encontra-se passado por referência à função “scanf”. Nota-se que, nas duas linhas, foram usadas
duas formas distintas para o acesso aos membros do registro.
  Até o momento, conversamos sobre alocaçõ es estáticas, as quais, temos que conhecer previamente a
quantidade de informaçõ es que serão manipuladas. Veremos a seguir, como podemos realizar alocaçõ es
dinâmicas e, mais especificamente, como podemos realizar busca, inserção e remoção de registros alocados
dinamicamente.

3.6.1 Operações sobre ponteiros: busca, inserção e remoção


Já que falamos sobre ponteiros e registros, que tal praticarmos operaçõ es básicas sobre uma lista de registros
usando ponteiros? Vamos voltar ao exemplo do registro que denota uma pessoa, e, a partir dele, vamos criar
uma lista para armazenar no máximo 10 pessoas. Para facilitar, vamos criar um registro descritor que contém
além do ponteiro da lista, um campo que armazena a quantidade de itens armazenados:

https://student.ulife.com.br/ContentPlayer/Index?lc=gd%2fd12LVVHhOTw1%2f21SPDQ%3d%3d&l=Cftg%2fqYAWV10o0QR%2fFXMCA%3d%… 26/31
22/02/2023, 16:54 Técnicas de Programação

Utilizando a estrutura acima, vamos implementar as funçõ es para realizar o processo de busca, inserção e
remoção de registros. Porém, inicialmente, temos que criar uma lista vazia, alocando o espaço para o
recebimento das informaçõ es relativas a no máximo 10 pessoas:

No có digo acima, a função “CriarListaVazia()” visa a alocação dinâmica do vetor com capacidade para o
armazenamento das informaçõ es relativas a 10 pessoas e a iniciação, com 0, do campo que indica a
quantidade de pessoas armazenadas.
A partir da criação da lista, poderemos, então, realizar as operaçõ es básicas. Vamos iniciar pela operação de
busca, cuja função é apresentada a seguir:

https://student.ulife.com.br/ContentPlayer/Index?lc=gd%2fd12LVVHhOTw1%2f21SPDQ%3d%3d&l=Cftg%2fqYAWV10o0QR%2fFXMCA%3d%… 27/31
22/02/2023, 16:54 Técnicas de Programação

Como se observa no có digo acima, o processo de busca é realizado percorrendo-se todo vetor “pPessoas” por
intermédio da utilização do índice “i” somado ao endereço base do ponteiro “listaP.pPessoas” de modo a
comparar o conteú do do campo “nome” com o argumento passado como parâmetro 
. Caso seja encontrado, o
endereço do item achado é copiado para o ponteiro
 e retornado o índice no qual encontra-se
o elemento encontrado.
Para a inserção na posição “pos”, é necessário realizar o deslocamento das informaçõ es para a direita a partir
da posição na qual ocorrerá a inserção. Esse deslocamento é mostrado através do có digo a seguir:

https://student.ulife.com.br/ContentPlayer/Index?lc=gd%2fd12LVVHhOTw1%2f21SPDQ%3d%3d&l=Cftg%2fqYAWV10o0QR%2fFXMCA%3d%… 28/31
22/02/2023, 16:54 Técnicas de Programação

Na função de inserção acima, nota-se que a cada iteração


  é feita uma có pia da célula “i - 1” para a
célula “i”, liberando-se, assim, a célula “pos” para receber as informaçõ es da pessoa a ser cadastrada

. Nesta etapa, foi utilizada a função “memcpy” (definida no arquivo header “string.h”) para efetuar a có pia das
informaçõ es de acordo com o formato: “memcpy(destino,fonte,quantidade_bytes);”. Além de efetuar o
deslocamento das informaçõ es dentro do vetor, essa função incrementa o campo que indica a quantidade de
itens no vetor .
Por fim, para realizar a remoção de um item da posição “pos”, pode-se proceder como exemplificado no
có digo a seguir:

Ao contrário da função de inserção, a remoção realiza um deslocamento do conteú do para a esquerda em cada
iteração do laço de repetição. Neste caso, a posição “i” recebe o conteú do da posição “i + 1”. Ao final do
deslocamento, a quantidade de itens armazenados no vetor é decrementada em uma unidade.
(https://www.youtube.com/watch?v=i_0IBJkXn2M)Na prática existem diversas outras estratégias para a
manipulação de estruturas usando a alocação dinâmica, dentre as quais podemos citar: listas, filas, pilhas e
árvores. (PUGA, 2016). Alocaçõ es dinâmicas são extremamente ú teis para a criação de có digos escaláveis.
Escalabilidade de um programa refere-se à sua facilidade para se adequar a outras dimensõ es de massa de
dados que será manipulada. Além das listas encadeadas, podemos usar a alocação dinâmica em outras
estruturaçõ es, tais como: listas duplamente encadeadas e árvores.

Síntese
Chegamos ao fim de nossa terceira conversa sobre técnicas de programação; nesta, pudemos ampliar o
universo da programação através da conceituação e experimentação da utilização de ponteiros. Conseguimos
verificar o uso de ponteiros nos processos de alocação estática e alocação dinâmica. Com os pontos
abordados, você já conseguirá implementar programas mais complexos e torná-los mais eficientes,
estruturados e escaláveis através da utilização dos ponteiros. Através dos conteú dos apresentados nesta
terceira unidade, esperamos que você continue o processo de incremento em relação à criação de programas
computacionais de modo a torná-los ainda mais eficientes, organizados e, agora, escaláveis. 
Nesta unidade, você teve a oportunidade de:

https://student.ulife.com.br/ContentPlayer/Index?lc=gd%2fd12LVVHhOTw1%2f21SPDQ%3d%3d&l=Cftg%2fqYAWV10o0QR%2fFXMCA%3d%… 29/31
22/02/2023, 16:54 Técnicas de Programação

• ter contato com conceitos inerentes aos ponteiros;


• analisar as vantagens para a manipulação de ponteiros;
• modelar vetores e matrizes através de ponteiros;
• conhecer e empregar estruturas de dados heterogêneas;
• analisar e utilizar alocações dinâmicas de memória.

Bibliografia
ASCENCIO, A. F. G. Fundamentos de Programação de Computadores: Algoritmos, PASCAL, C/C++ (Padrão ANSI)
e Java. 3. ed. São Paulo: Pearson Education do Brasil, 2012.   Disponível em:   <https://
 nimabrasil.blackboard.com/>. Acesso em: 11/07/2019. 
DEITEL, P. J.; DEITEL, H. C: Como Programar. 6. ed. São Paulo: Pearson Prentice Hall, 2011.   Disponível em:
 <https://Â nimabrasil.blackboard.com/>. Acesso em: 11/07/2019.
FERREIRA, D. Como funciona memó ria: de C a JavaScript (memory management). 2017. 22 min. Disponível
em: <https://www.youtube.com/watch?v=82yMCuCY2-k (https://www.youtube.com/watch?v=82yMCuCY2-
k)>. Acesso em 11/07/2019.
GARCIA, F. D. Ponteiro em C: Funçõ es. 2015. Disponível em:   <https://www.embarcados.com.br/ponteiro-
em-c-funcoes/ (https://www.embarcados.com.br/ponteiro-em-c-funcoes/)>. Acesso em:  03/07/2019.
LACERDA, L.C.; RAMOS, J.M.B. Instituto Federal de Educação, Ciência e Tecnologia. Programação orientada a
objetos. Aula 01. Rondô nia, 2015. 1h15min. Disponível em: < https://www.youtube.com/watch?v=l-
CaVliXaA0 (https://www.youtube.com/watch?v=l-CaVliXaA0)>. Acesso em: 11/07/2019.
MELLO, R. Introdução ao Funcionamento da Memória Stack e Heap. 11:45min. 2015. Disponível em:
<https://www.youtube.com/watch?v=i_0IBJkXn2M (https://www.youtube.com/watch?v=i_0IBJkXn2M)>.
Acesso em: 14/07/2019.
MICROSOFT. Campos de Bits C. 2016. Disponível em:   < (https://docs.microsoft.com/pt-br/cpp/c-
language/c-bit-fields?view=vs-2019)https://docs.microsoft.com/pt-br/cpp/c-language/c-bit-fields?view=vs-
2019 (https://docs.microsoft.com/pt-br/cpp/c-language/c-bit-fields?view=vs-2019)>. Acesso em:
11/07/2019.
MIZRAHI, V. V. Treinamento em Linguagem C. 2. ed. São Paulo: Pearson Prentice Hall, 2008.  Disponível em:
<https://Â nimabrasil.blackboard.com/>. Acesso em: 11/07/2019.
PUGA, S.; RISSETTI, G. Ló gica de Programação e Estruturas de Dados – com Aplicaçõ es em Java. 3. ed. São
Paulo: Pearson Education do Brasil, 2016.   Disponível em:   <https://Â nimabrasil.blackboard.com/>. Acesso
em: 11/07/2019.
ROBERTS, S. Conheça o cientista considerado o ‘guia espiritual’ dos algorítimos. The New York Times. Nova
York, 25, dez 2018. International Weekly Estadão. Disponível em: <
https://internacional.estadao.com.br/noticias/nytiw,conheca-o-cientista-considerado-o-guia-espiritual-dos-
algoritmos,70002654893 (https://internacional.estadao.com.br/noticias/nytiw,conheca-o-cientista-
considerado-o-guia-espiritual-dos-algoritmos,70002654893)>. Acesso em 11/07/2019. 

https://student.ulife.com.br/ContentPlayer/Index?lc=gd%2fd12LVVHhOTw1%2f21SPDQ%3d%3d&l=Cftg%2fqYAWV10o0QR%2fFXMCA%3d%… 30/31
22/02/2023, 16:54 Técnicas de Programação

https://student.ulife.com.br/ContentPlayer/Index?lc=gd%2fd12LVVHhOTw1%2f21SPDQ%3d%3d&l=Cftg%2fqYAWV10o0QR%2fFXMCA%3d%… 31/31

Você também pode gostar