[1] Comentário enviado por
elgio em 18/04/2008 - 10:00h:
Oi. legal esta tua iniciativa de se escrever um artigo sobre malloc, mas veja que algumas de suas afirmações, mesmo que corretas, podem induzir ao erro se o inexperiente programador não souber contextualizá-las (e o experiente não precisaria ler este artigo ;-)
Primeiro, quando se programa em C ANSI deve-se cuidar do respeito aos padrões ANSI. A forma de alocação que sugeriste de alocar um espaço em relação à uma variável não funciona em todos os casos, logo para que se arriscar a usar:
printf("\nDigite o tamanho da string: ");
scanf("%d",&valor);
char string[valor];
E se o cara digitar -1 para valor? (-1 será interpretado como 2.147.483.647, ou seja, alocaria 2G, aproximadamente!!!). Induz ao erro. Eu prefiro JAMAIS, em HIPÓTESE ALGUMA ensinar estas coisas para quem está iniciando.
Outra indução ao erro é que SEMPRE que se faz malloc deve-se testar o seu retorno. Pode ser que tu não consigas alocar a memória que solicitou:
printf("\nDigite o tamanho da string: ");
scanf("%d",&tamanho);
string= malloc( tamanho * sizeof(char) ); /*o sizeof ajuda a aumentar a portabilidade*/
printf("\nDigite a string: ");
scanf("%s",string);
(e poderiamos ainda discutir o problema de buffer overflow que o scanf permite. Eu ensinaria direto o fgets)
E se DENOVO, o usuário digitar -1? Ou mesmo 1000000 e não se tem memória? Veja que o programa continua e vais escrever em uma área NÃO ALOCADA o que é GRAVÍSSIMO! Sempre, sempre, sempre, sempre se deve testar se o malloc funcionou:
printf("\nDigite o tamanho da string: ");
scanf("%d",&tamanho);
string= malloc( tamanho * sizeof(char) );
if (string == NULL){
fprintf(stderr, "ERRO NO MALLOC\n");
return(1);
}
printf("\nDigite a string: ");
fgets(string, tamanho, stdin);
[2] Comentário enviado por
removido em 18/04/2008 - 10:04h:
Para gerar matrizes dinamicamente, talvez seja mais indicado o uso de calloc:
void *calloc(size_t nmemb, size_t size);
Que está definido em stdlib.h. Nele você especifica quantos membros terá na sua matriz e qual o tamanho deles.
[3] Comentário enviado por
elgio em 18/04/2008 - 10:06h:
calloc é praticamente um define:
calloc (3,4) == malloc(3*4)
[4] Comentário enviado por
elgio em 18/04/2008 - 10:09h:
"A desvantagem da alocação dinâmica está no rompimento da pilha de memória, o que causaria o fechamento do programa e também, com a alocação dinâmica, o programa torna-se mais lento, pois ela requer muito do processamento. "
Como assim?
rompimento de pilha? malloc não usa a pilha para alocação e este rompimento e fechamento de um programa é somente se não conseguiu alocar e o programador não testou. Usado de forma correta não há nenhum rompimento e nenhum fechamento de programa!
E mais lento?
Nada disso.
Depois de alocado o acesso é na mesma velocidade do que vetores estáticos. A lentidão existe no momento de alocar, pois a alocação é uma tarefa onerosa (que pode envolver até - PASMEM - defragmentação de memória).
Abraços.
[5] Comentário enviado por
ulissescosta em 18/04/2008 - 19:47h:
scanf("%d",&valor);
char string[valor];
Isto não é alocação dinâmica de memória!
No máximo podes alocar 2GB que é o tamanho máximo da stack relativa a variáveis.
[6] Comentário enviado por
maran em 20/04/2008 - 14:54h:
caramba, olha os cara meu, aula de programação....
Isso ae show de bola o artigo e os comentarios
[7] Comentário enviado por
FelipeAbella em 24/04/2008 - 19:29h:
calloc(a,b) é igual a malloc (a*b)
com exceção de que calloc zera a memória alocada.
É possível evitar um buffer overflow no scanf:
char str[16];
scanf("%15s", str);
Boa iniciativa.
[8] Comentário enviado por
elgio em 24/04/2008 - 19:51h:
calloc: Correto!
Eu prefiro não perder este tempo extra com esta inicialização
scanf: Correto também, mas o fgets é muito mais intuitivo.
Com fgets o tamanho pode ser um #define ou mesmo uma variável:
#define MAX 200
...
fgets(str, MAX, stdin);
Porque isto NÃO FUNCIONA:
scanf("%MAXs", str);
Não funciona até porque teria que ser MAX-1 (para o fgets tu passa o tamanho do buffer e ele já sabe que precisa de um para o 0. Já no scanf é quantos cars e ele não reserva 1 para o zero.)
O scanf permite inclusive livrar-se do inconveniente de não ler espaços em branco:
scanf("%[^\n]s", str);
Mas ai já é coisa par aum artigo avançado (poderes ocultos do scanf...)
[9] Comentário enviado por
odavai em 28/04/2008 - 08:50h:
gostei vou utilizalo depois enviarei se deu tudo certo nos meus estudos de c e c++
[10] Comentário enviado por
gdm.arc em 31/10/2008 - 12:47h:
Senhores(as)
Saudações
Gostaria de dizer que o código está com alguns problemas, segue abaixo o código modificado visto não ter funcionado o inicial apresentado no presente artigo, aliás muito interessante.
Os seguintes pontos de erro foram encontrados:
1) tipo da variável de entrada via scanf não era compativel com unsigned short int, visto estar retornando sempre zero ao invés do valor digitado.
2) a sintaxe do malloc() omitia o casting. A função malloc() retorna um ponteiro 'void', que precisa ser 'moldado' ao ser atribuido.
3) atribuição do valor ao invés do endereço para a variável "matriz" na chamada ao malloc() na primeira dimensão.
4) comentário incorreto na chamada da função free() para a segunda dimensão.
5) o sizeof() deve ser usado para o ponteiro e não para o valor apontado pelo ponteiro
Agradecido.
Parabéns pela iniciativa
gdm.arc
#include <stdio.h>
#include <stdlib.h>
/*includes*/
int main(void)
{
int linhas, colunas, i; /* (1) */
int **matriz;
printf("\nDigite o número de linhas e colunas: ");
scanf("%d,%d",&linhas, &colunas);
matriz= (int **) malloc( linhas * sizeof( int *) ); /* (2),(3),(5) */
for(i=0;i<linhas;i++)
matriz[i]= (int *) malloc( colunas * sizeof( int ) ); /* (2) */
/*a partir deste ponto pode ser usado matriz[a][b] sendo a o número da linha e b o número da coluna para qualquer parte do programa*/
for(i=0; i<linhas; i++)
free(matriz[i]); /* (4) */
free(matriz); /*faz a liberação da memória alocada*/
return 0;
}
[11] Comentário enviado por
inacioalves em 29/10/2009 - 23:16h:
Reativando o tópico.
1. Me corrijam se eu estiver errado, mas pelo menos em C ANSI basta incluir a biblioteca stdlib.h para podermos usar malloc e sizeof.
2. Não se faz necessário trabalhar com ponteiros de ponteiros para usarmos "matrizes".
Considerem o código abaixo:
#include<stdio.h>
#include<stdlib.h>
int main(){
int i,j, l,c;
float *m;
scanf("%d%d",&l,&c);
m = malloc( l*c*sizeof(float) );
for( i=0; i<l; i++ )
for(j=0;j<c;j++ )
scanf("%f",m+(i*c+j) );
for( i=0; i<l; i++ ){
for(j=0;j<c;j++ )
printf("%8.2f",*(m+i*c+j) );
printf("\n");
}
return 0;
}
Ele trata muito bem um vetor como se este fosse uma matriz ;)
[12] Comentário enviado por
ElisMacedo em 28/10/2011 - 22:21h:
// Isso é um trecho de um programa,coloquei somente a parte que usamos para alocar dinamicamicana a quantidade de filas e a quantidade de cadeiras da primeira fileira de um teatro.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//DEFINIÇÕES DAS VARIAVEIS
#define MAX 26 //Numero máximo de filas
#define CASE_1 1 // Vender cadeira isolada
#define CASE_2 2 // Vender lote de cadeiras
#define CASE_3 3 //Consultar cadeiras com folga
#define CASE_4 4 // consultar cadeiras com vista livre
#define CASE_5 5 //Fechar bilheteria
#define CASE_6 6 //Mostrar ocupação total do teatro
#define CASE_7 7 //Sair do programa
//Protótipo das funções
int ** cria_fileiras_int(int , int); //Função para criar a matriz de alocação para criar as filas e cadeiras do teatro
void vender_cadeira(int **, float , int , int, char[]); // função para vender cadeiras isoladas
void vender_lote(int **, float , int , int, char[]); //Função pra vender cadeiras por lote
void teatro_total(int ** ,int ,int , char[]); //Função para exibir a matriz das cadeiras com folga
void vista_livre(int ** ,int ,int , char[]); //Funçao para exibir as caderias com vista livre
void fechar_bilheteria(int **, int , int , float, char[]); //Função para calcular o faturamento total da bilheteria, taxa de ocupação total e por fila
void ocupacao(int ** ,int ,int , char[]); //Função que mostra o teatro
//Início do prgrama
int main(){
int escolha; // guarda a opção do menu
int n; // guarda quantidade de fila
int c; // guarda a quantidade de cadeiras
int ** teatro; //vetor de ponteiro que aponta para a matriz teatro
float preco = 0;// guarda o preço
char * escolhas[] = {"Vender uma cadeira isolada",
"Vender um lote de cadeiras",
"Consultar cadeiras com folga",
"Consultar cadeiras com vista livre",
"Fechar bilheteria",
"Mostrar a ocupacao total do Teatro",
"Finalizar programa"};
char fileira[] = {'A','B','C','D','E',
'F','G','H','I','J',
'K','L','M','N','O',
'P','Q','R','S','T',
'U','W ','X','Y','Z'};
printf("Insira a quantidade de fileiras totais: "); //Solicita ao usuário que digite a quantidade de filas e cadeiras da primeira fila
scanf("%d", &n);
printf("Insira a quantidade de cadeiras da 1a fileira: ");
scanf("%d", &c);
while(n<2 || n>MAX){ // Verifica os parâmetros digitados
printf("Minimo de 2 e maximo de 26 fileiras no teatro!!\n");
printf("Insira a qtde de fileiras totais e cadeiras da 1a fileira): ");
scanf("%d %d",&n,&c);
}
//Função para criar a matriz de alocaçao para criar as filas e cadeiras do teatro
int ** cria_fileiras_int(int n, int c) {
int ** mat, i;
if((mat = (int **) calloc(n,sizeof(int *))) == NULL) {
return NULL;
}
for(i = 0; i < n ; i++) {
if((mat[i] = (int *) calloc(c + 2 * i, sizeof(int))) == NULL) return NULL; // c+2*iacrescentar 2 cadeiras a cada nova fileira
}
return mat;
}