| <<< Voltar | Avançar >>> |
15. Gerenciamento de memória
15.1 Preenchendo um intervalo de memória com uma constante byte
Para preencher um intervalo de memória utilize a função memset() . No gcc ela faz parte do arquivo de cabeçalho string.h e sua sintaxe é:
*memset(*STRING,CARACTER,BYTES) |
a função acima preenche BYTES da área de memória apontada por *STRING com CARACTER . A função retorna um ponteiro para *STRING .
Ao preencher strings com esta função, pelo menos no ambiente Linux usando o gcc, a função não inseriu o caracter NULL para indicar o final da string, assim tive que fazer isso eu mesmo. Exemplo:
/* preechendo uma área de memória usando a função memset() */
#include <stdio.h>
#include <string.h>
int main()
{
char nome[10];
memset(nome,'s',10);
/* inserindo o valor NULL para indicar o final da string */
nome[10] = 0;
printf("%s\n",nome);
return(0);
}
|
15.2 Copiando um intervalo de memória
Para copiar um intervalo de memória use a função memcpy() . Ela faz parte do arquivo de cabeçalho string.h e sua sintaxe é:
*memcpy(*DESTINO,*ORIGEM,BYTES) |
a função acima copia BYTES da área de meória *ORIGEM para a área de memória *DESTINO . A função retorna um ponteiro para *DESTINO . Exemplo:
/* copiando um intervalo de memória */
#include <stdio.h>
#include <string.h>
int main()
{
float nrs1[5] = {1.1,1.2,1.3,1.4,1.5};
float nrs2[5] = {5,5,5,5,5};
int contador;
printf("valores de nrs1\n");
for(contador = 0;contador < 5;contador++)
printf("%.1f ",nrs1[contador]);
printf("\n");
printf("valores de nrs2 inicialmente\n");
for(contador = 0;contador < 5;contador++)
printf("%.1f ",nrs2[contador]);
printf("\n");
memcpy(nrs2,nrs1,sizeof(nrs1));
/* observe o uso do operador "sizeof" para
* determinar o tamanho da área de memória
* a ser copiada
*/
printf("valores de nrs2 após a cópia\n");
for(contador = 0;contador < 5;contador++)
printf("%.1f ",nrs2[contador]);
printf("\n");
return(0);
}
|
15.3 Movendo um intervalo de memória
Para mover uma área de memória use a função memmove() que está no arquivo de cabeçalho string.h . Sua sintaxe é:
*memmove(*DESTINO,*ORIGEM,BYTES) |
a função acima move BYTES da área de memória *ORIGEM para a área de memória *DESTINO . A função retorna um ponteiro para *DESTINO . A diferença entre esta função e a função memcpy() mostrada na seção anterior é que com esta as área de memória *DESTINO e *ORIGEM podem se sobrepor. Exemplo:
/* movendo um intervalo de memória */
#include <stdio.h>
#include <string.h>
int main()
{
float nrs[5] = {1.1,1.2,1.3,1.4,1.5};
float *ptr_nrs;
int contador,bytes;
printf("valores de nrs inicialmente\n");
for(contador = 0;contador < 5;contador++)
printf("%.1f ",nrs[contador]);
printf("\n");
ptr_nrs = nrs;
ptr_nrs++;
bytes = (sizeof(float) * 4);
memmove(nrs,ptr_nrs,bytes);
printf("valores de nrs após a movimentação\n");
for(contador = 0;contador < 5;contador++)
printf("%.1f ",nrs[contador]);
printf("\n");
return(0);
}
|
15.4 Copiando até encontrar um byte específico
Usando a função memccpy() , que está no arquivo de cabeçalho string.h você pode copiar um intervalo de memória até encontrar um byte específico. A sintaxe da função é;
*memccpy(*DESTINO,*ORIGEM,CARACTER,BYTES) |
Ela copia, no máximo, BYTES de *ORIGEM para *DESTINO , parando se CARACTER for encontrado. Ela retorna um ponteiro para o próximo byte após CARACTER em *DESTINO ou NULL se CARACTER não for encontrado nos primeiros BYTES de *ORIGEM . Exemplo:
/* copiando um intervalo de memória até encontrar um
* byte específico */
#include <stdio.h>
#include <string.h>
int main()
{
char frase[80] = "E como dizia meu velho professor de física...estudem!!!";
char copia[80];
char *ptr_copia;
/* "ptr_copia" aponta para o resultado de memccpy().
* Se o caracter "." for encontrado em "frase",
* será efetuada a cópia da área de memória até
* este caracter e "ptr_copia" apontará para o
* próximo byte após "." em "copia.
* Caso contrário, serão copiados 80 bytes e
* "ptr_copia" receberá o valor NULL.
*/
ptr_copia = memccpy(copia,frase,'.',80);
if(ptr_copia)
*ptr_copia = 0;
printf("%s\n",copia);
return(0);
}
|
15.5 Comparando duas áreas de memória
Você pode comparar duas áreas de memória usando a função memcmp() . Ela faz parte do arquivo de cabeçalho string.h e sua sintaxe é:
memcpy(*AREA1,*AREA2,BYTES) |
Ela compara os primeiros BYTES de *AREA1 e *AREA2 .Se *AREA1 for maior ela retorna um inteiro maior que zero, se *AREA2 for maior ela retorna um inteiro menor que zero e caso as duas áreas sejam iguais ela retorna zero. Exemplo:
/* comparando duas áreas de memória */
#include <stdio.h>
#include <string.h>
int main()
{
char string1[7] = "aeiou";
char string2[7] = "Aeiou";
int resultado;
printf("string1 = %s\n",string1);
printf("string2 = %s\n\n",string2);
resultado = memcmp(string1,string2,7);
if(resultado > 0)
printf("string1 é maior\n");
else if(resultado < 0)
printf("string2 é maior\n");
else
printf("string1 e string2 são iguais\n");
return(0);
}
/* Faça algumas substituições no código
* trocando o "A" maiúsculo de "string2"
* para "string1" e/ou substituindo-o
* por um "a" e observe os vários
* resultados do programa.
*/
|
15.6 Trocando bytes adjacentes
Quando você precisar trocar os bytes adjacentes, normalmente para trocar dados entre máquinas que possuem ordenamento de bytes alto/baixo diferentes, use a função swab() . Ela faz parte do arquivo de cabeçalho string.h e sua sintaxe é:
swab(*ORIGEM,*DESTINO,BYTES) |
Ela copia BYTES de *ORIGEM para *DESTINO trocando os bytes adjacentes, pares e ímpares. Exemplo:
/* trocando bytes adjacentes */
#include <stdio.h>
#include <string.h>
int main()
{
char str_origem[30] = "Trocando bytes adjacentes";
char str_destino[30];
memset(str_destino,'s',30);
str_destino[30] = 0;
printf("str_origem => %s\n",str_origem);
printf("str_destino => %s\n",str_destino);
printf("chamando swab()\n");
swab(str_origem,str_destino,30);
printf("str_origem => %s\n",str_origem);
printf("str_destino => %s\n",str_destino);
return(0);
}
|
15.7 Alocando memória dinamicamente
Quando você declara uma matriz o compilador aloca memória para o armazenamento dos dados desta matriz. Caso você queira alterar o tamanho da matriz terá que modificar o código e recompilar o programa. Para evitar isso você pode alocar memória dinamicamente, ou seja, o programa aloca a memória necessária durante a execução. Para isso você pode usar as funções calloc() e malloc() . Em ambiente linux, usando o gcc, elas fazem parte do arquivo de cabeçalho stdlib.h .
A sintaxe de calloc() é:
*calloc(QUANTIDADE_DE_ELEMENTOS,TAMANHO) |
Ela aloca memória para uma matriz com o número de elementos igual a QUANTIDADE_DE_ELEMENTOS , tendo cada um destes elementos TAMANHO bytes. Esta função retorna um ponteiro para o ínicio do bloco de memória alocado ou NULL caso ocorra algum problema.
Exemplo do uso de calloc() :
/* alocando memória dinamicamente com calloc() */
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *matriz1;
int nr_elementos_matriz1;
int contador;
printf("Alocando memória dinamicamente usando calloc()\n");
printf("Entre com a quantidade de elementos
da matriz de inteiros :");
scanf("%d",&nr_elementos_matriz1);
matriz1 = (int *) calloc(nr_elementos_matriz1,sizeof(int));
/* Observe acima a instrução "(int *)". Isto é usado
* para converter o ponteiro retornado por calloc()
* para um ponteiro do tipo desejado. Caso você
* estivesse alocando memória para um ponteiro de
* ponto flutuante esta instrução seria "(float *").
*/
if(matriz1)
{
for(contador = 0;contador < nr_elementos_matriz1;contador++)
{
printf("Entre com o %do elemento :",contador + 1);
scanf("%d",&matriz1[contador]);
}
printf("\n");
for(contador = 0;contador < nr_elementos_matriz1;contador++)
printf("Exibindo o %do elemento : %d\n",
contador + 1,matriz1[contador]);
}
else
printf("Erro ao alocar memória.\n");
return(0);
}
|
A sintaxe de malloc() é:
*malloc(BYTES) |
Esta função aloca BYTES e retorna um ponteiro para o início da memória alocada ou NULL caso ocorra algum problema.
Exemplo do uso de malloc() :
/* alocando memória dinamicamente com malloc() */
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *matriz1;
int contador;
int nr_elementos_matriz1;
printf("Alocando memória dinamicamente usando malloc()\n");
printf("Entre com a quantidade de elementos da matriz de inteiros :");
scanf("%d",&nr_elementos_matriz1);
matriz1 = (int *) malloc(nr_elementos_matriz1 * sizeof(int));
/* Observe acima a instrução "(int *)". Isto é usado
* para converter o ponteiro retornado por malloc()
* para um ponteiro do tipo desejado. Caso você
* estivesse alocando memória para um ponteiro de
* ponto flutuante esta instrução seria "(float *").
*/
if(matriz1)
{
for(contador = 0;contador < nr_elementos_matriz1;contador++)
{
printf("Entre com o %do elemento :",contador + 1);
scanf("%d",&matriz1[contador]);
}
printf("\n");
for(contador = 0;contador < nr_elementos_matriz1;contador++)
printf("Exibindo o %do elemento : %d\n",
contador + 1,matriz1[contador]);
}
else
printf("Erro ao alocar memória.\n");
return(0);
}
|
15.8 Liberando memória
Quando seu programa não precisar mais da memória alocada com as funções malloc() e calloc() ele deve liberar a memória. Para isso você pode usar a função free() , que pertence ao arquivo de cabeçalho stdlib.h e cuja sintaxe é:
free(*PONTEIRO) |
Exemplo do uso de free() :
/* liberando memória anteriormente alocada */
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *matriz1;
int contador;
int nr_elementos_matriz1;
printf("Alocando memória dinamicamente usando malloc()\n");
printf("e liberando a memória alocada com free()\n");
printf("Entre com a quantidade de elementos da matriz de inteiros :");
scanf("%d",&nr_elementos_matriz1);
matriz1 = (int *) malloc(nr_elementos_matriz1 * sizeof(int));
if(matriz1)
{
for(contador = 0;contador < nr_elementos_matriz1;contador++)
{
printf("Entre com o %do elemento :",contador + 1);
scanf("%d",&matriz1[contador]);
}
printf("\n");
for(contador = 0;contador < nr_elementos_matriz1;contador++)
printf("Exibindo o %do elemento : %d\n",
contador + 1,matriz1[contador]);
free(matriz1); /* liberando a memória alocada */
}
else
printf("Erro ao alocar memória.\n");
return(0);
}
|
15.9 Alterando o tamanho da memória alocada
Para alterar o tamanho de um bloco de memória anteriormente alocado use a função realloc() . Ela faz parte do arquivo de cabeçalho stdlib.h e sua sintaxe é:
*realloc(*PONTEIRO,BYTES) |
Ela altera o tamanho do bloco apontado por *PONTEIRO para BYTES . A memória recém-alocada não será inicializada. Se *PONTEIRO for NULL, a chamada será equivalente a malloc(BYTES) ; se BYTES for igual a zero, a chamada será equivalente a free(*PONTEIRO) . A menos que *PONTEIRO seja NULL, ele precisa ter sido retornado por uma chamada anterior para malloc() , calloc() ou realloc() .
Exemplo do uso de realloc() :
/* alterando um bloco de memória anteriormente alocado */
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *frase;
frase = (char *) malloc(10);
if(frase)
printf("10 bytes alocados com sucesso\n");
else
printf("Erro ao alocar memória\n");
printf("\n");
realloc(frase,1000);
if(frase)
printf("1000 bytes alocados com sucesso\n");
else
printf("Erro ao alocar memória\n");
return(0);
}
|
| <<< Voltar | Avançar >>> |