Ir para conteúdo
Fórum Script Brasil
  • 0

Alocando Memória Com Malloc()


Castro

Pergunta

:(


..........
..........
int *p;

p = malloc(50 * sizeof (int));

if ( p == NULL)
 {
  printf (“falha”);
  exit (1);
 }

printf (“O valor alocado é %d”, p);

...............
.................

O valor de p é: 40240336

1) Suponho que o valor acima seja lixo. Achei que como o tipo inteiro tem 2 bytes, ao fazer 50 * 2 eu teria 100 bytes alocados para o ponteiro p Mas pelo visto não é isto que ocorre. O que está errado ?

2) O que faz exit (1) diferente de exit(0) ?.

Obrigado,

Link para o comentário
Compartilhar em outros sites

20 respostass a esta questão

Posts Recomendados

  • 0

:(


..........
..........
int *p;

p = malloc(50 * sizeof (int));

if ( p == NULL)
 {
  printf (“falha”);
  exit (1);
 }

printf (“O valor alocado é %d”, p);

...............
.................

O valor de p é: 40240336

1) Suponho que o valor acima seja lixo. Achei que como o tipo inteiro tem 2 bytes, ao fazer 50 * 2 eu teria 100 bytes alocados para o ponteiro p Mas pelo visto não é isto que ocorre. O que está errado ?

Creio que você terá 50 posições para preencher com inteiros, ou seja, de p[0] até p[49]. E, estas posições não são necessariamente inicializadas com um valor, por isso você receberá qualquer valor ao tentar mostrá-las.

2) O que faz exit (1) diferente de exit(0) ?.

Emite um nível de erro (errorlevel) de valor 1, que significa que o programa foi terminado com algum erro (quando não há erro, o nível é 0). Você pode capturar esse tipo de informação com um arquivo de lote (.bat), através de instruções específicas.

Abraços,

Graymalkin

Link para o comentário
Compartilhar em outros sites

  • 0

3) Com base na resposta dada, qual a forma correta de se iniciar as 50 posições, sem lixo ?

O iSoron respondeu acima. Você poderia também fazer um loop inicializando explicitamente cada posição.

4) Qual a diferença de se escrever a função malloc() como acima, e esta abaixo ?

p= (int*) malloc(50 *sizeof(int));

A diferença é que você está explicitamente dizendo que quer um ponteiro para um inteiro (int *). Aliás, aqui no Dev-C++ só funciona desta maneira (o do seu primeiro exemplo dá erro).

Abraços,

Graymalkin

Link para o comentário
Compartilhar em outros sites

  • 0

..

..

5) passei a escrever p= (int*) malloc(50 *sizeof(int)); e a variável “p” continuou a apresentar o mesmo valor acima. Acho que ainda Não entendi o que é esse valor. No meu entendimento eu deveria Ter o valor 100, ou seja 100 posições para 50 variáveis inteiras. Estou errado ?

6) Se eu estiver errado, então devo concluir, que alocação dinâmica só pode ser usada com matrizes, porque ai, eu seria obrigado a usar todas a posições contíguas de memória necessária para os elementos da matriz, conclui certo ?

7) Qual a versão de seu compilador Dev C++, pergunto isso, porque coloquei e tirei (int*) e não deu erro de compilação algum ( estou usando versão 4 -gratuita).

8) O outro companheiro de fórum sugeriu usar calloc() ao invés de malloc(). Li a descrição das duas, e não vi diferença ou vantagem. Tem alguma ?

Obrigado,

Link para o comentário
Compartilhar em outros sites

  • 0

5) passei a escrever p= (int*) malloc(50 *sizeof(int)); e a variável “p” continuou a apresentar o mesmo valor acima. Acho que ainda Não entendi o que é esse valor. No meu entendimento eu deveria Ter o valor 100, ou seja 100 posições para 50 variáveis inteiras. Estou errado ?

a funcão malloc retorna um ponteiro para a posicão de memoria alocada

então isso é apenas um endereco.

8) O outro companheiro de fórum sugeriu usar calloc() ao invés de malloc(). Li a descrição das duas, e não vi diferença ou vantagem. Tem alguma ?

a vantagem é que a memoria é zerada.

Link para o comentário
Compartilhar em outros sites

  • 0

5) passei a escrever p= (int*) malloc(50 *sizeof(int)); e a variável “p” continuou a apresentar o mesmo valor acima. Acho que ainda Não entendi o que é esse valor. No meu entendimento eu deveria Ter o valor 100, ou seja 100 posições para 50 variáveis inteiras. Estou errado ?

A memória de um computador é dividida em milhões de bytes, cada um com um número único que o identifica. Quando você chama a função malloc, ela procura por uma área de memória que ainda não esteja sendo usada por ninguém, e te retorna o número identificador do primeiro byte. A quantidade de bytes reservada é a mesma que você pediu, então não faria sentido retorná-la.

6) Se eu estiver errado, então devo concluir, que alocação dinâmica só pode ser usada com matrizes, porque ai, eu seria obrigado a usar todas a posições contíguas de memória necessária para os elementos da matriz, conclui certo ?

Não necessariamente. Na verdade, o uso mais comum do malloc é quando se quer colocar uma variável no heap, e não na pilha. Por exemplo, quando você cria uma variável dentro de uma função e deseja retornar o seu endereço.

7) Qual a versão de seu compilador Dev C++, pergunto isso, porque coloquei e tirei (int*) e não deu erro de compilação algum ( estou usando versão 4 -gratuita).

O Dev-C++ não é um compilador. Ele é apenas uma IDE (ou seja, editor de texto, menus, coloração de código, etc). O compilador que você está usando é, provavelmente, o GNU GCC, que, por sinal, é o mesmo usado no linux.

8) O outro companheiro de fórum sugeriu usar calloc() ao invés de malloc(). Li a descrição das duas, e não vi diferença ou vantagem. Tem alguma ?

Como o Kandrade disse, a diferença é que o calloc limpa a memória depois de alocar.

Se você tentar acessar, vai ver que todos os elementos são zero.

Té mais,

Link para o comentário
Compartilhar em outros sites

  • 0

:(

9) Com base nesse papo todo, devo concluir, que só variáveis tipo ponteiro podem ser usadas para alocar memória, Correto ?

10) considere a citação abaixo:

Se diz que as variáveis locais ocupam uma posição específica na memória – A pilha, as variáveis alocadas comportam –se como variáveis globais, pois ocupam posição arbitrária na memória. Contudo, há uma diferença entre variáveis globais e alocadas, as variáveis globais são definidas em tempo de compilação, enquanto as variáveis alocadas são definidas em tempo de execução. Portanto o tamanho de uma variável alocada pode ser definido em função de parâmetros que somente são conhecidos em tempo de execução. Isso da enorme flexibilidade para o programador

Dá para colocar isso em miúdos ? Não vejo tanta vantagem assim, apesar da portabilidade, se uma máquina não tiver memória suficiente em relação a uma outra, o programa terá a mesma dificuldade de ser rodado indepemdente da alocação, ou não ?

Fonte: e-booke C/C++ e orientação a objetos em ambiente multiplataforma – versão 5.1

11) Considere a citação abaixo

Os programas que alocam memória devem ter o cuidado de liberar a memória que não precisam mais. A memória alocada permanece indisponível para outros usos, mesmo que o programa que tenha alocado a memória tenha terminado.

Fonte: e-booke C/C++ e orientação a objetos em ambiente multiplataforma – versão 5.1

Devo concluir, que se eu não usar a função free(nome_da_variável_alocada), mesmo ao finalizar meu programa, ficarei com aquela porção de memória alocada, e por conseqüência menos memória disponível ? mesmo que o programa seja feito em C, e não em C++ ?

12 ) Um dos companheiros disse, que meu programa exemplo lá em cima está errado. Algum de vocês pode corrigi-lo ?

Obrigado,

Link para o comentário
Compartilhar em outros sites

  • 0

:(

int *p[11],i;

 p = (int*) malloc(11 * sizeof (int));

   .
   .

for (i=0; i<11;i++)
    {
    printf ("O valor alocado para  p %d\n",*p[i]);
    }

free (p);

Resolvi segar a sugestão do isoron e “criar um loop inicializando automaticamente cada posição.” Para minha alegria, recebi a seguinte mensagem de erro:

“10 d:\fontec\sizeof.c

incompatible types in assignment”.

Pessoal a pergunta 12 continua valendo. agora então

Link para o comentário
Compartilhar em outros sites

  • 0

11) Considere a citação abaixo

Os programas que alocam memória devem ter o cuidado de liberar a memória que não precisam mais. A memória alocada permanece indisponível para outros usos, mesmo que o programa que tenha alocado a memória tenha terminado.

Fonte: e-booke C/C++ e orientação a objetos em ambiente multiplataforma – versão 5.1

até onde sei, depende do SO

o Linux libera a memoria para ser usada sim, depois que o programa é terminado.

o Window deve fazer o mesmo, não tem razão pra continuar alocado um espaco de memória pra algo que não existe mais.

12 ) Um dos companheiros disse, que meu programa exemplo lá em cima está errado. Algum de vocês pode corrigi-lo ?

não sei é isso que voce quer:

#include <stdio.h>

int main(){

int *p,i;

p =  malloc(11 * sizeof (int));

for (i=0; i<11;i++)
    {
    printf ("O valor alocado para  p[%d] %d\n",i,*(p+i));
    }

     free (p);


   exit(0);
}

Link para o comentário
Compartilhar em outros sites

  • 0

:(

int *p[11],i;

 p = (int*) malloc(11 * sizeof (int));

   .
   .

for (i=0; i<11;i++)
    {
    printf ("O valor alocado para  p %d\n",*p[i]);
    }

free (p);

Resolvi segar a sugestão do isoron e “criar um loop inicializando automaticamente cada posição.” Para minha alegria, recebi a seguinte mensagem de erro:

“10 d:\fontec\sizeof.c

incompatible types in assignment”.

Cadê a inicialização? Você *não* está atribuindo um valor para cada posição.

Abraços,

Graymalkin

Link para o comentário
Compartilhar em outros sites

  • 0

:(

int *p[11],i;

p = (int*) malloc(11 * sizeof (int));

..............
..............
for (i=0; i<11;i++)
    {
     p[i] =&i; /* inicializando p */
    printf ("O valor alocado para  p %d\n",*p[i]);
    }

..........................................
..........................................

Fiz a inicialização, entretanto, a mensagem de erro permanece.

“10 d:\fontec\sizeof.c

incompatible types in assignment”

O erro recai na linha que aloca as 11 posições de memória. Não estou visualizado o motivo do erro, já que fiz a inicialização da variável ‘p’ dentro do FOR. O que estou fazendo errado ?

Link para o comentário
Compartilhar em outros sites

  • 0

o erro acontece porque voce cria 11 variáveis ponteiro para int

então qual delas voce vai alocar memoria?

por exemplo a primeira:

int *p[11],i;

p[0] = (int*) malloc(11 * sizeof (int));

..............
..............
for (i=0; i<11;i++)
    {
     p[i] =&i; /* inicializando p */
    printf ("O valor alocado para  p %d\n",*p[i]);
    }

ou se voce não quiser criar 11 variáveis ponteiro, apenas uma, na declaração faca isso:
int *p,i;

p = (int*) malloc(11 * sizeof (int));

..............
..............
for (i=0; i<11;i++)
    {
     p[i] =&i; /* inicializando p */
    printf ("O valor alocado para  p %d\n",*p[i]);
    }

abraço!!!

Link para o comentário
Compartilhar em outros sites

  • 0

13) Kandrade, Ok, funcionou. Mostrei os valores de 0 até 10. Fiz o seguinte:

:)


..........
..........
for (i=0; i<11;i++)
    {
     p[i] = (int*) malloc(11 * sizeof (int));
    }
...................
..................
for (i=0; i<11;i++)
    {
     p[i] =&i; /* inicializando p */
    printf ("O valor alocado para  p %d\n",*p[i]);
    }
..........
........
free(p);

Daí pergunto: Se estou alocando uma matriz de ponteiros inteiros, uma simples free(p), libera todas as posições de memória ? a função free() funciona como matriz passada como argumento de função, ou seja, basta passar o endereço do primeiro elemento da matriz e o resto é encontrado porque está em posição contígua de memória ?

14) experimentei das duas formas que você falou. A versão acima, e p[0] = (int*) malloc(11 * sizeof (int)); nos dois casos deu certo. Isto quer dizer, que a posição 0 foi alocada na memória livre, e as posições de 1 à 10 não. Pergunto em termos práticos, qual a vantagem de se alocar uma variável ou uma matriz em memória livre ? não percebi mudança de desempenho, ou qualquer outro ganho significativo.

PS a pergunta 10 continua valendo a afirmativa, lá feita é correta ? As distribuições Linux ainda vem com gcc no pacote ?

Obrigado.

Link para o comentário
Compartilhar em outros sites

  • 0

14) experimentei das duas formas que você falou. A versão acima, e p[0] = (int*) malloc(11 * sizeof (int)); nos dois casos deu certo. Isto quer dizer, que a posição 0 foi alocada na memória livre, e as posições de 1 à 10 não.

isso, olha como funciona

voce tem 11 variáveis ponteiro para int, a primeira delas, ou seja, p[0] foi alocada em 11 posições para inteiros.

p[1] poderia tambem ser alocada em 11 posições para inteiros.

percebe a diferença?

o retorno de malloc é para a posição inicial da memória alocada então p[0] tem 11 posições alocadas para inteiros

e de p[1] a p[10] nada foi alocado, só foi declarado.

Daí pergunto: Se estou alocando uma matriz de ponteiros inteiros, uma simples free(p), libera todas as posições de memória ? a função free() funciona como matriz passada como argumento de função, ou seja, basta passar o endereço do primeiro elemento da matriz e o resto é encontrado porque está em posição contígua de memória ?

sim, todas as 11 posições alocadas em p[0] seram liberadas, eu só não tenho certeza se voce tivesse alocado p[1] a p[11] se ele liberaria.

As distribuições Linux ainda vem com gcc no pacote ?

sim, a grande maioria delas

Link para o comentário
Compartilhar em outros sites

  • 0

:(

15) Então continuando. Tome por exemplo o último programa, que foi o que deu cerato. Seguindo o raciocínio, se eu alocar as 11 posições na memória livre, eu teria as variáveis de p[0] à p[10] alocadas na memória livre de forma contígua, com malloc() retornando para a primeira posição. Certo ? daí continuo com minha dúvida prática, se quando uso ponteiros, já estou trabalhando com memória, ganhando performance, que vantagem tenho em alocar memória livre para essa 11 variáveis ? Kandrade e pessoal do fórum vocês não acham essa questão instigaste ? enxergar essa sutileza não seria chave no estudo de C ?

16) Com relação ao liberação de memória :

Até onde sei depende do S.O o Linux libera memória para ser usada sim..... O Windows deve fazer o mesmo......

Quando o Windows reclama de falta de memória durante a execução de algum programa ou conjunto de programas, não seria exatamente a falha do uso de alguma dessas funções de liberação de memória ?

17) O Graymalkin, diz no post #5, que fazendo malloc() com (int*), estou explicitando que se quer um ponteiro para inteiro. Li que quando se faz isto, está se fazendo um CAST (conversão de tipo). Pergunto: Se o retorno, é um ponteiro para o tipo inteiro, por que especificar ou converter tipo ?

Link para o comentário
Compartilhar em outros sites

  • 0

15) Então continuando. Tome por exemplo o último programa, que foi o que deu cerato. Seguindo o raciocínio, se eu alocar as 11 posições na memória livre, eu teria as variáveis de p[0] à p[10] alocadas na memória livre de forma contígua, com malloc() retornando para a primeira posição. Certo ?

não, olha esse código abaixo e tire suas conclusões:

.
.
.
int main() {
int *p[11],i;

p[0] = (int *) malloc(11 * sizeof (int));
p[1] = (int *) malloc(11 * sizeof (int));

printf("*****varendo p[0]*****\n");
for (i=0; i<11;i++)
    {
    *p[0]=i;
    printf ("valor: %d    posicao memoria: %p\n",*p[0],p[0]);
    p[0]++;
    }
    free(p[0]);
printf("*****varendo p[1]*****\n");
for (i=0; i<11;i++)
    {
    *p[1]=i;
    printf ("valor: %d    posicao memoria: %p\n",*p[1],p[1]);
    p[1]++;
    }
    free(p[1]);
    
    getch();
return 0;
}

Quando o Windows reclama de falta de memória durante a execução de algum programa ou conjunto de programas, não seria exatamente a falha do uso de alguma dessas funções de liberação de memória ?

realmente, eu não uso muito windows, mas pode ser sim um porblema desse tipo.

17) O Graymalkin, diz no post #5, que fazendo malloc() com (int*), estou explicitando que se quer um ponteiro para inteiro. Li que quando se faz isto, está se fazendo um CAST (conversão de tipo). Pergunto: Se o retorno, é um ponteiro para o tipo inteiro, por que especificar ou converter tipo ?

não, malloc retorna um ponteiro VOID, por isso a conversão para INT.

Link para o comentário
Compartilhar em outros sites

  • 0

:(

18)Ao rodar seu programa, tive a impressão, de que os endereços de memória da variável p[0] e p[1], são seqüenciais. Conclui corretamente ?

Fiz os seguintes experimentos com seu programa:

18-1) No 1o teste: transformei a variável ponteiro *p, e uma variável inteiro p. Tive como resposta, a seguinte mensagem de erro:

4 c:\meusdo~1\s.c

warning: assignment makes integer from pointer without a cast

C:\Meus documentos\S.c compiled successfully

18-2) No 2o teste: Fiz p = malloc(11 * sizeof (int)); tirei o (int*), e tive como resultado

Valor 0 posição memória 00000000

..............................................................

..............................................................

Valor 10 posição memória 0000000A

Ou seja parece que neste caso a variável ponteiro não fez muita falta por que ?, me parece que esta é uma outra forma de ver as posições de memória.

Outro ponto, que me chamou a atenção, é que parece que o fato de eu ter deixado de usar matriz seja de inteiro ou ponteiro para inteiro parece não ter feito diferença. E ai pergunto por que preciso usar ponteiro para alocar memória ? Favor comente.

18-3) No 3o teste: retornei o programa as condições originais

Valor 0 posição memória 02660480

..............................................................

..............................................................

Valor 10 posição memória 026604A8

E fiz o seguinte teste:

Aumentei o laço do comando for da variável p[0] de11 para 13. Achei que ao fazer isso, receberia alguma mensagem de erro. Para minha surpresa, não acusou nenhum erro. Entretanto ao ver o resultado do programa, tiver como resultado:

.........................................................

Valor 11 posição memória 026604AC

Valor 12 posição memória 026604B0

Pensei, que o incremento p[0]++ estaria condicionado a linha:

p[0] = (int *) malloc(11 * sizeof (int)); entretanto, acho que não isso que ocorre não deveria apontar para uma região invalida e dar erro ? por que isso ?

18-4) Retornei o programa as condições originais, criei o código abaixo, e testei o seguinte:

int *p,i;

p = (int*) malloc(11 * sizeof (int));

for (i=0; i<11;i++)
    {
     p =&i; /* inicializando p */
    printf ("O valor de p %d,  O endereço alocado para p %p\n",*p, p);
    p++;
    }

Neste teste, todos os valores variaram e os endereços foram repetidos. O que me sugeriu, que em seu código, p[0], apesar de ser um elemento de matriz ponteiros para inteiros, funcionaria como uma matriz de endereços. Isto é correto ?

18-5) Modifique a linha de meu código de p =&i para *p =i; e as coisas funcionaram como no seu programa, ou seja 10 valores correspondendo a 10 endereços diferentes . Sei que o operador unário *, fornece conteúdo da variável, e o operador & fornece o endereço. Por isso achei que através do endereço dos valores poderia mostrar os próprios endereços. O que estava errado nessa idéia ?

18-5) Entretanto, fiz *p=&i; , e funcionou como *p =i; por que nesse caso são formas equivalentes ?

18-6) Sempre se sugere, que após a alocação de memorai, faça o teste do ponteiro nulo (if p==NULL)) por que seu programa não utilizou este expediente ?

Obigado.

Link para o comentário
Compartilhar em outros sites

  • 0

E fiz o seguinte teste:

Aumentei o laço do comando for da variável p[0] de11 para 13. Achei que ao fazer isso, receberia alguma mensagem de erro. Para minha surpresa, não acusou nenhum erro. Entretanto ao ver o resultado do programa, tiver como resultado:

.........................................................

Valor 11 posição memória 026604AC

Valor 12 posição memória 026604B0

Pensei, que o incremento p[0]++ estaria condicionado a linha:

p[0] = (int *) malloc(11 * sizeof (int)); entretanto, acho que não isso que ocorre não deveria apontar para uma região invalida e dar erro ? por que isso ?

No caso, como sabemos que a memória é dividida em milhões de bytes, cada um com um identificador único, e todos contíguos, o ponteiro apenas aponta para a base de array alocado, ou seja, para a primeira posição do seu vetor. Porém, não se sabe até onde vai o seu array, isso quer dizer que você terá que controlar até onde pode-se incrementar ou decrementar seu ponteiro (se for o caso) para referir-se as posições do array alocado. Fazendo com que seu ponteiro referêncie uma área que não pertence ao seu array (indiferente do tipo de alocação) se houver memória (o que é mais provável) disponível, ele irá apontar prá lá.

Espero que tenha entendido!

Dê uma olhada nos tutoriais "apontados" pelo brother kandrade e qualquer coisa é só falar.

Abraços,

William Rodrigues

Link para o comentário
Compartilhar em outros sites

Participe da discussão

Você pode postar agora e se registrar depois. Se você já tem uma conta, acesse agora para postar com sua conta.

Visitante
Responder esta pergunta...

×   Você colou conteúdo com formatação.   Remover formatação

  Apenas 75 emoticons são permitidos.

×   Seu link foi incorporado automaticamente.   Exibir como um link em vez disso

×   Seu conteúdo anterior foi restaurado.   Limpar Editor

×   Você não pode colar imagens diretamente. Carregar ou inserir imagens do URL.



  • Estatísticas dos Fóruns

    • Tópicos
      152,1k
    • Posts
      651,9k
×
×
  • Criar Novo...