malloc invalid conversion

malloc invalid conversion

por André Luis Porto da Silva -
Número de respostas: 6
Olá Professor, estou com uma dúvida quanto ao uso do malloc()

ElemSilhueta *sr;
sr = malloc(2*sizeof(ElemSilhueta));

O compilador retorna erro com a seguinte mensagem:

error: invalid conversion from `void*' to `ElemSilhueta*'

Não entendi... não estou convertendo nada... apenas atribuindo o endereço do malloc para o sr... gostaria de saber o porquê desse erro e como proceder para dribla-lo.
Obrigado.
Em resposta à André Luis Porto da Silva

Re: malloc invalid conversion

por Natan Costa Lima -
Justamente, você não está convertendo e deveria. A função malloc devolve um ponteiro void* a sua chamada deveria ser:

sr = (ElemSilhueta *)malloc(2*sizeof(ElemSilhueta));

Em resposta à André Luis Porto da Silva

Re: malloc invalid conversion

por Francisco Reverbel -
Esse erro indica que você está usando o compilador no modo C++ e não no modo C.

Na linguagem C os ponteiros para void (void *) têm uma característica especial: eles são compatíveis com quaisquer outros ponteiros (como por exemplo ElemSilhueta *) e podem ser atribuídos a outros ponteiros sem necessidade de nenhuma conversão. Em classe eu faço atribuições assim a toda hora.

Já na linguagem C++ os ponteiros para void não têm essa característica e portanto precisam ser convertidos explicitamente para ponteiros de outros tipos, do jeito que o Natan indicou.

O gcc (e consequentemente o Code::Blocks, que usa o gcc) pode funcionar tanto no modo de compilador C como no modo de compilador C++. O erro em questão só aparece quando o compilador é usado no modo C++. A forma correta de eliminá-lo é usar o compilador no modo C, em vez de sair colocando conversões explícitas no programa.

As conversões explícitas entre void * e outros tipos de ponteiros são ruins porque elas escondem o problema verdadeiro, que é o uso do compilador no modo C++. Existem outros casos em que faz diferença usar o modo C ou o modo C++. Em outras palavras, o uso do compilador no modo errado pode causar outros problemas. Se você continuar usando o modo C++, é muito provável que na correção do seu programa apareçam erros de compilação, pois a correção será feita no modo C. Aproveite a ocasião para mudar para o modo C!


Em resposta à Francisco Reverbel

Re: malloc invalid conversion

por Ângelo de Souza Chiode -

Aqui também estava dando esse erro, professor!

Mas... como eu faço para alterar o compilador de C++ para C?

Obrigado sorriso

Em resposta à André Luis Porto da Silva

Re: malloc invalid conversion

por André Luis Porto da Silva -
Muito obrigado.
Mudei o compilador para C somente.
Mas acontece um problema quando eu aloco a memória.
É da seguinte forma:
Eu tenho dois pointers de ElemSilhueta: s1 e s2
Quando faço a seguinte alocação:

ElemSilhueta *sr;
sr = malloc(2*sizeof(ElemSilhueta));

Os valores de s1 ou s2 são alterados...
Exemplo:

As seguintes linhas de comando:

printf("s1 == %d %d , %d %d\n", s1->x, s1->h, (s1+sizeof(ElemSilhueta))->x, (s1+sizeof(ElemSilhueta))->h);
printf("s2 == %d %d , %d %d\n\n", s2->x, s2->h, (s2+sizeof(ElemSilhueta))->x, (s2+sizeof(ElemSilhueta))->h);

ElemSilhueta *sr;
sr = mallocX(2*sizeof(ElemSilhueta));

printf("s1 == %d %d , %d %d\n", s1->x, s1->h, (s1+sizeof(ElemSilhueta))->x,(s1+sizeof(ElemSilhueta))->h);
printf("s2 == %d %d , %d %d\n", s2->x, s2->h, (s2+sizeof(ElemSilhueta))->x, (s2+sizeof(ElemSilhueta))->h);

Retornam como saída:

s1 == 1 2 , 8 0
s2 == 4 5 , 6 0

s1 == 1 2 , 8 0
s2 == 1 2 , 4064272 4064272


O que pode estar acontecendo nesse caso?
Desde ja agradeço.
Em resposta à André Luis Porto da Silva

Re: malloc invalid conversion

por Francisco Reverbel -
O que não está fazendo sentido é o uso de s1+sizeof(ElemSilhueta) e de s2+sizeof(ElemSilhueta). Se s1 e s2 são endereços de silhuetas (sendo cada silhueta um vetor de estruturas ElemSilhueta), então você pode fazer acesso a cada elemento desses vetores usando a notação vetorial ou a notação de ponteiros. Como vimos em aula, essas duas notações são equivalentes.

Na notação vetorial, os campos x e h do primeiro elemento de s1 são s1[0].x e s1[0].h, os do segundo elemento são s1[1].x e s1[1].h, os do terceiro elemento são s1[2].x e s1[2].h, etc.

Na notação de ponteiros, os campos x e h do primeiro elemento de s1 são s1->x e s1->h, os do segundo elemento são (s1+1)->x e (s1+1)->h, os do terceiro elemento são (s1+2)->x e (s1+2)->h, etc.

Pela definição da aritmética de ponteiros, quando você soma 1 a um ponteiro o que é adicionado ao endereço físico é o tamanho do tipo apontado pelo ponteiro. Assim, na soma s1+1 o que é adicionado ao endereço físico já é sizeof(ElemSilhueta)! Você não precisa (e não deve) escrever s1+sizeof(ElemSilhueta)!!!

Quando a gente usa s1+i, o valor adicionado ao endereço físico é i*sizeof(ElemSilhueta), de modo que o resultado é o endereço do elemento que está i posições à frente. Como você usou s1+sizeof(ElemSilhueta), o valor adicionado ao endereço físico foi o quadrado do tamanho de um elemento (sizeof(ElemSilhueta)*sizeof(ElemSilhueta)) e portanto o programa fez acesso ao lugar errado na memória. Se você tiver sorte, esse lugar errado cai fora do programa e você toma um segmentation fault. Se você tiver num dia de má sorte, você acaba lendo ou escrevendo em alguma outra variável do seu programa. Aí o programa se comporta de um jeito estranho e ninguém entende a razão...

É por essas e outras que muita gente (a maioria das pessoas?) acha a notação vetorial (s1[i].x) mais fácil de entender e de usar que a notação de ponteiros ((s1+i)->x)... Se a notação de ponteiros estiver atrapalhando você, mude para a vetorial!

Em resposta à Francisco Reverbel

Re: malloc invalid conversion

por André Luis Porto da Silva -
Muito obrigado novamente professor...
Acabei confundindo as coisas por aqui...
Duvida sanada... Peço desculpas...
E muito obrigado novamente...