Ir para conteúdo

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Toleds

Alocação Dinamica em funções

Recommended Posts

Boa noite a todos!

Eu estou fazendo um trabalho para a faculdade mas estou com um problema que não consigo resolver.

 

Eu gostaria de saber como faço para passar os valores de uma matriz V, cuja memória foi alocada dinamicamente dentro de uma função, de volta para uma matriz na função main. Para explicar melhor, abaixo está a parte do código em que estou tendo problema:

 

 


void Ler_Imagem (int Col, int Lin, int ***v)
...
...
...
v = (int *) calloc (Lin , sizeof(int *));
for (i=0; i < Lin; i++)
{
v = (int *) calloc (Col , sizeof(int));
}
for (i = 0; i < Lin; i++)
{
for (j = 0; j < Col; j++)
{
fscanf(inFile, "%d", &v[j]);
}

 

int main()
{
int NumCol, NumLin;
int **v;
NumCol = 0; NumLin = 0;
Ler_Imagem(NumCol, NumLin, &v);
}
Eu passo v por referencia para a função "Ler Imagem"... Nesta função, os valores de Linhas e Colunas da matriz sao obtidos, e com eles, eu uso alocação dinamica para determinar o tamanho de V.... Depois, eu gravo na matriz V os valores obtidos de um arquivo que foi aberto na função "Ler imagem"... E a partir disso eu queria jogar essa matriz obtida (que foi gravada em V) de volta para a função main, mas nao estou conseguindo entender como.
Espero que alguem possa me ajudar, eu ficaria muuuito agradecido.
Obs: Eu não postei por completo a função "Ler_Imagem" pois acredito que não seja necessário, mas se alguem precisar do resto dela para poder me ajudar, é so falar q eu coloco ela por completo.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Alguns conceitos básicos parecem estar confusos na sua cabeça. É normal, mas vamos corrigi-los:

 

1. Não existe passagem por referência em C. Argumentos são sempre passados por valor. Dizer f(&x) passa o valor do endereço do objeto x, e não uma referência a ele. Em um sistema com passagem por referência, a função (hipotética) f(x) { x = 10 } altera o valor de x no contexto em que a função é invocada. Isso nunca ocorre em C. Parece um detalhe minúsculo, mas se você aprofundar seus estudos em linguagens de programação, vai evitar problemas graves se já entender o conceito hoje.

 

2. Cuidado com os tipos que você está usando pra alocação. Se o tipo do parâmetro v é (int ***), como você disse ao declarar a função Ler_Imagem, você precisa armazenar dentro de v valores de tipo (int ***). Portanto a chamada de calloc está errada, pois explicita o tipo (int *) e determina o número de bytes como múltiplos de (int *). O mesmo vale para as iterações do seu for, onde você designa a *(v + i) (de tipo (int **)) valores com cast a (int *), e calculados como múltiplos de (int *).

 

3. calloc, malloc, etc, retornam valores de tipo (void *). A conversão de (void *) a (T *), sendo (T) um tipo de objeto (como, por exemplo, (int)), é natural e benigna. Portanto o melhor seria fazer int *p = malloc(3 * sizeof (int));.

 

4. sizeof é um operador, e não uma função. Em C, essa diferença é importante, porque nos deixa dizer coisas como sizeof *p ao invés de sizeof (int). A primeira forma é preferível por ser mais coesa (se resolvermos mudar o tipo de p mais tarde, o lado direito da expressão T *p = malloc(sizeof *p); não precisa ser corrigido). Se sizeof fosse uma função, sizeof *a causaria comportamento indefinido se o valor de a fosse indeterminado (como são os valores de p e v nestes exemplos).

 

 

Dito isto tudo, e ignorando os erros de tipos e conselhos acima, ao dizer Ler_Imagem(..., &v);, o valor de v pode ser atualizado pela própria função Ler_Imagem. Portanto você já pode usar v sabendo que vai apontar para o primeiro elemento do primeiro vetor para dentro do qual v aponta.

 

Geralmente, em C, temos 2 "correntes" relacionadas à forma como valores são passados entre funções:

 

A primeira, que acho mais elegante, envolve funções que simplesmente retornam um valor como resultado:

 

 

int **v = ler_imagem();
 
if (!v)
{
    // Houve algum problema...
}
 
// Não houve problema, continuar normalmente e usar v.

 

A segunda, que parece que te recomendaram, envolve passar um ponteiro como argumento, que apontará, depois que a função retornar, para o resultado da computação. Geralmente essa tática é preferida quando o valor de retorno da função não é o objetivo final pelo qual ela existe, e sim um indicador de status de execução:

 

 

int v[x][y];
 
status_t s = ler_imagem(&v);
 
switch (s)
{
 
    // Avaliar todos os casos e definir qual foi o resultado da função.
    // Se for o caso, abortar o programa ou tratar o erro.
 
}
 
// Continuar normalmente e usar v.

 

A forma que eu prefiro nem sempre é sustentável, porque geralmente transfere pelo menos parte da responsabilidade de tratamento de erros para dentro da função (ou, pior, alteração de estado de objetos externos de monitoramento de erro, que aumenta acoplamento). Mas procuro atingi-la sempre que possível. Pra mim parece mais simples.

 

Abs

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.