Você está na página 1de 32

Alocação dinâmica

Alocação dinâmica vs Estática

• Na alocação estática, o espaço para


as variáveis é reservado no inicio
da execução:
Ex:
– int idade;
– float notas[40];

• Na alocação dinâmica, o espaço para


as variáveis é alocado dinamicamente
durante a execução do programa.
Liberação de memória
• A memória deve ser liberada após o
término de seu uso.
• A liberação deve ser feito por
quem fez a alocação.
– Alocação estática: compilador
– Alocação dinâmica: programador
Funções para alocação
dinâmica
• Iremos trabalhar com 4 funções
disponíveis na biblioteca stdlib
– Alocação de memória
• malloc
• calloc
• realloc
– Liberação de memória
• free
sizeof()
Para auxiliar no processo de alocação de
memória iremos utilizar a função sizeof.

int sizeof(tido_de_dado);

A função recebe um tipo de dado e retorna a


quantidade de bytes necessários para alocar
um único elemento deste tipo de dado.

Podemos usá-la de duas maneiras:

sizeof(tipo_de_dado)
sizeof variável
Exemplo sizeof()
#include <stdio.h>
#include <stdlib.h>

int main() {
int x;
float y;
printf("Qtde de bytes para CHAR: %d\n", sizeof(char));
printf("Qtde de bytes para INT: %d\n", sizeof(int));
printf("Qtde de bytes para FLOAT: %d\n", sizeof(float));
printf("Qtde de bytes para DOUBLE: %d\n", sizeof(double));
printf("Qtde de bytes para X: %d\n", sizeof x);
printf("Qtde de bytes para Y: %d\n", sizeof y);
return 0;
}
malloc()
• A função malloc() serve para alocar memória
durante a execução do programa. Ela recebe a
quantidade de bytes que será alocada, faz o pedido
de memória e retorna um ponteiro com o endereço do
inicio do espaço de memória alocado.

FORMA GERAL

void *malloc(unsigned int num)

• Entrada da função
– num: quantidade de bytes na memória a serem alocados

• Retorno da função
– NULL: Caso haja erro
– Ponteiro que aponta para a primeira posição de
memória alocada.
Exemplo I malloc()
#include <stdio.h>
#include <stdlib.h>

int main() {
int *p, *p2;
//aloca memória para 1000 char
p = (char *) malloc(1000);
//aloca memória para 250 int
p2 = (int *) malloc(1000);
return 0;
}
Exemplo II malloc()
#include <stdio.h>
#include <stdlib.h>

int main() {
int *p, i;
p = (int *) malloc(5 * sizeof (int));
if (p == NULL){
printf("Erro ao alocar memoria!");
exit(1);
}
for (i = 0; i < 5; i++){
p[i] = rand() % 10;
printf("%d\t", p[i]);
}
return 0;
}
calloc()
• A função calloc() aloca memória durante a execução
do programa e retorna um ponteiro com o endereço
da primeira posição de memória alocada, assim como
a função malloc().

FORMA GERAL
void *calloc(unsigned int num, unsigned int tamanho);

• A diferença é que a função calloc() recebe dois


parâmetros de entrada.
– num: número de elementos no array a ser alocado;
– tamanho: o tamanho de cada elemento do array, ou
seja, a quantidade de bytes alocado na memória para
cada elemento.
• E retorna
– NULL, no caso de erro;
– Ponteiro para a posição do primeiro elementos do
array

A função calloc inicializa todos os bits alocados com 0.


Exemplo I calloc()
#include <stdio.h>
#include <stdlib.h>

int main() {
int *p, i;
p = (int *) calloc(5, sizeof (int));
if (p == NULL){
printf("Erro ao alocar memoria!");
exit(1);
}
for (i = 0; i < 5; i++){
printf("%d\t", p[i]);
}
return 0; Saída
} 0 0 0 0 0
realloc()
• A função realloc() serve para alocar memória ou
realocar blocos de memória previamente alocados
pelas funções malloc(), calloc() ou realloc().

FORMA GERAL
void *realloc(void *ponteiro, unsigned int num);

• A função realloc() recebe dois parâmetros de


entrada
– Um ponteiro para um bloco de memória previamente
alocado
– Quantidade de bytes para ser alocado.

• E retorna
– NULL, caso haja algum erro.
– O ponteiro para primeira posição do array
alocado/realocado.
Exemplo I realloc()

int *x, i;
x = (int *) malloc(40 * sizeof(int));
for (i = 0; i < 40; i++)
x[i] = rand() % 10;
x = (int *) realloc(x, 80 * sizeof(int));
x = (int *) realloc(x, 20 * sizeof(int));
x = (int *) realloc(x, 0);
Exemplo II realloc()
#include <stdio.h>
#include <stdlib.h>
int main() {
int i;
int *p = malloc(5 * sizeof(int));
for (i = 0; i < 5; i++){
p[i] = rand() % 9;
printf("%d\t", p[i]);
}
//diminuir tamanho do array
p = realloc(p, 3 * sizeof(int));
for (i = 0; i < 3; i++)
printf("%d\t", p[i]);
//aumenta o tamanho do array
p = realloc(p, 10 * sizeof(int));
for (i = 0; i < 10; i++)
printf("%d\t", p[i]);
return 0;
}
free()
• As funções vistas anteriormente servem para
alocar espaços de memória. Ao contrário
delas, a função free() irá liberar espaços
de memória alocados.

FORMA GERAL
void free(void *ponteiro);

Espaços de memória alocados dinamicamente


não são liberados ao final da execução do
programa, como ocorrem com as demais
variáveis. Por isso é necessário sempre
utilizar a função free() ao final para
liberar o espaço de memória alocado
anteriormente.
Exemplo free()
#include <stdio.h>
#include <stdlib.h>

int main() {
int *p, i;
p = (int *) malloc(5 * sizeof (int));
if (p == NULL){
printf("Erro ao alocar memoria!");
exit(1);
}
for (i = 0; i < 5; i++){
p[i] = rand() % 10;
printf("%d\t", p[i]);
}
free(p);
p = NULL;
return 0;
}
O que será impresso?
int a[10], *b;
b = a;
b[2] = 25;
printf("%d\n", a[2]);
printf("%d\n", b[2]);

int a[10], *b;


b = (int *) malloc(10 * sizeof(int));
b[2] = 25;
printf("%d\n", a[2]);
printf("%d\n", b[2]);
Exercício
• Aloque dinamicamente um vetor de
tamanho N e preencha-o com
inteiros aleatórios de 0 a 99.
• Escreva uma função que receba este
vetor e retorne a soma dos
elementos pares que antecedem e
sucedem elementos ímpares
#include <stdio.h>
#include <stdlib.h>
Resposta
int soma(int *v, int t){
int i, s = 0;
for (i = 1; i < t - 2; i++){
if (!(v[i] % 2) && (v[i - 1] % 2) && (v[i + 1] % 2))
s += v[i];
}
return s;
}
int main() {
int i, t, *vet;
do {
scanf("%d", &t);
} while (t < 1);

vet = (int *) malloc(t * sizeof(int));

for (i = 0; i < t; i++){


vet[i] = rand() % 100;
printf("%d ", vet[i]);
}
printf("\nSoma: %d\n", soma(vet, t));
return 0;
}
Exercício
• Crie um programa que:
– Aloque dinamicamente um array de 4
números inteiros,
– Receba do teclado 4 números armazene no
espaço alocado,
– Mostre na tela os 4 números
– Realoque o espaço do array para caber
mais 5 números inteiros
– Preencha o novo espaço com números
aleatórios
– Mostre na tela os 9 números
– Libere a memória alocada.
#include <stdio.h>
#include <stdlib.h>
Resposta
int main() {
int *v, i;

v = (int *) malloc(4 * sizeof(int));

for (i = 0; i < 4; i++)


scanf("%d", &v[i]);

for (i = 0; i < 4; i++)


printf("%d ", v[i]);

v = (int *) realloc(v, 9 * sizeof(int));


for (i = 4; i < 9; i++)
v[i] = rand() % 10;

printf("\n");
for (i = 0; i < 9; i++)
printf("%d ", v[i]);

return 0;
}
Alocação de arrays multidimensionais
• Sabendo que um array é uma sequência
adjacente de posições na memória, podemos
alocar espaço para uma matriz da mesma forma
que fazemos com um vetor, ou seja, alocar um
array de uma única dimensão e tratá-lo como
se fosse uma matriz (2 dimensões).
Exemplo:
int *p = (int *) malloc((4 * 4) * sizeof(int));
Alocação dinâmica de matrizes
#include <stdio.h>
Solução I
#include <stdlib.h>

int main() {
int i, j, lin, col, *p;
lin = 2;
col = 2;
p = (int *) malloc(lin * col * sizeof(int));
for (i = 0; i < lin; i++){
for (j = 0; j < col; j++)
p[i * col + j] = rand() % 10;
}
for (i = 0; i < lin; i++){
for (j = 0; j < col; j++)
printf("%d ", p[i * col + j]);
printf("\n\n");
}
free(p);
p = NULL;
return 0;
}
#include <stdio.h> Alocação dinâmica de matrizes
#include <stdlib.h>
void preencheMatriz(int *m, int lin, int col){ Solução I – com função
int i, j;
for (i = 0; i < lin; i++){
for (j = 0; j < col; j++)
m[i * col + j] = rand() % 10;
}
}
void imprimeMatriz(int *m, int lin, int col){
int i, j;
for (i = 0; i < lin; i++){
for (j = 0; j < col; j++)
printf("%d ", m[i * col + j]);
printf("\n\n");
}
}

int main() {
int lin, col, *matriz;
lin = 2;
col = 2;

matriz = (int *) malloc(lin * col * sizeof(int));


preencheMatriz(matriz,lin,col);
imprimeMatriz(matriz,lin,col);

free(matriz);
matriz = NULL;

return 0;
}
Alocação de arrays multidimensionais
• Se quisermos alocar um array com mais de uma
dimensão e manter a notação de colchetes
para cada dimensão, precisamos utilizar o
conceito de "ponteiro para ponteiro".
Exemplo: int **p;
Matriz na memória
#include <stdio.h> Alocação dinâmica de matrizes
#include <stdlib.h>
int main() { Solução II
int i, j, lin, col, **mat;
lin = col = 2;

mat = (int **) malloc(lin * sizeof(int));


for (i = 0; i < lin; i++)
mat[i] = (int *) malloc(col * sizeof(int));

for (i = 0; i < lin; i++){


for (j = 0; j < col; j++)
mat[i][j] = rand() % 10;
}
for (i = 0; i < lin; i++){
for (j = 0; j < col; j++)
printf("%d ", mat[i][j]);
printf("\n\n");
}
//liberando espaço alocado para matriz
for (i = 0; i < lin; i++)
free(mat[i]);
free(mat);
mat = NULL;
return 0;
}
#include <stdio.h> Alocação dinâmica de matrizes
#include <stdlib.h>
Solução II – com função
void preencheMatriz(int **m, int lin, int col){
int i, j;
for (i = 0; i < lin; i++){
for (j = 0; j < col; j++)
m[i][j] = rand() % 10;
}
}
void imprimeMatriz(int **m, int lin, int col){
int i, j;
for (i = 0; i < lin; i++){
for (j = 0; j < col; j++)
printf("%d ", m[i][j]);
printf("\n\n");
}
}
int main() {
int lin, col, **mat;
lin = col = 5;

mat = (int **) malloc(lin * sizeof(int));


for (i = 0; i < lin; i++)
mat[i] = (int *) malloc(col * sizeof(int));

preencheMatriz(mat, lin, col);


imprimeMatriz(mat, lin, col);

for (i = 0; i < lin; i++)


free(mat[i]);
free(mat);
mat = NULL;
return 0;
}
Problema
• Aloque espaço para uma matriz M de
l linhas e c colunas. Preencha-a
com valores aleatórios de 5 a 20.
• Escreva uma função que receba a
matriz M e modifique-a somando 2 a
todos elementos da colunas ímpares
e subtraindo 3 de todos elementos
da colunas pares.
Resposta
#include <stdio.h> int main() {
#include <stdlib.h> int l, c, i, j, **m;
int modificaMatriz(int **m, int l, int c){
int i, j; l = 2; c = 3;
for (i = 0; i < l; i++){ m = (int **) calloc(l, sizeof(int));
for (j = 0; j < c; j++){ for (i = 0; i < l; i++)
if (j % 2) m[i] = (int *) calloc(c, sizeof(int));
m[i][j] += 2;
if (!i % 2) for (i = 0; i < l; i++){
m[i][j] -= 3; for (j = 0; j < c; j++)
} m[i][j] = rand() % 15 + 5;
} }
}
void imprimeMatriz(int **m, int l, int c){ imprimeMatriz(m, l, c);
int i, j; modificaMatriz(m, l, c);
for (i = 0; i < l; i++){ imprimeMatriz(m, l, c);
for (j = 0; j < c; j++) return 0;
printf("%d\t", m[i][j]); }
printf("\n\n\n");
}
}
Problema
• Escreva uma função que receba dois
inteiros l e c e retorna uma
matriz com l linhas e c colunas.
Faça chamada da função do programa
principal
Resposta
#include <stdio.h>
#include <stdlib.h>

void **geraMatriz(int l, int c){


int **m;

m = calloc(l, sizeof(int));
for (i = 0; i < l; i++)
m[i] = calloc(c, sizeof(int));

return m;
}

int main() {
int **matriz;
matriz = (int **) geraMatriz(3,5);
}

Você também pode gostar