1. Introdução
[1] Comentário enviado por
ymc em 18/05/2004 - 09:39h:
Ótimo artigo. Não tinha visto nada sobre o uso de ponteiros para void.
Só não entendi muito bem sua utilidade. O ponteiro de void pode armazenar
qualquer tipo de ponteiro sem dar erro?
[2] Comentário enviado por
jllucca em 18/05/2004 - 12:09h:
Sim.
Mas, eh boa pratica realizar cast pro tipo pra evitar problemas e ficar mais claro. Assim:
#include <stdio.h>
void main( void )
{
int x = 5;
void *y = (void *) &x;
int *z;
z = (int *) y;
*z = 9;
}
[3] Comentário enviado por
ctrlc em 18/05/2004 - 14:59h:
Bom artigo,
realmente acresento um conceito que nao conhecia.
[4] Comentário enviado por
ron_lima em 20/05/2004 - 07:17h:
O ponteiro void é interessante quando se deseja programar funções que operem sobre dados genéricos. A biblioteca Standard C utiliza-se largamente dos ponteiros para void. Por exemplo, a função memcpy tem o seguinte protótipo:
void * memcpy (void * dest, const void * orig, size_t len);
Uma implementação sugerida seria:
void * memcpy (void * dest, const void * orig, size_t len) {
size_t i;
char * o, d;
for (o=(char *)orig, d=(char *)dest; i<len; ++i, ++d, ++o) {
*d = *o;
}
return dest;
}
Observe que o casting para os ponteiros internos da função são necessários. Caso contrário, não seria possível a operação de deslocamento dos ponteiros. Esta implementação sugerida da função memcpy (que pode ser achada em stdlib.h) opera sobre qualquer tipo de dado contíguo em memória. Óbvio que é uma função que deve ser utilizada com cuidado, pois não existe qualquer checagem de tipo. Se você fornecer uma origem de dados de tipo maior que o destino com toda certeza irá provocar uma bela invasão de memória no seu programa. Se tiver sorte, a invasão levará o programa a cair com falha de segmentação (sinal 11). Na pior das hipóteses outra variável no stack irá "acolchoar" a invasão e você nunca vai poder pegar este problema...
[5] Comentário enviado por
jllucca em 20/05/2004 - 16:15h:
To fazendo o artigo dois e tava falando disso disso... o cast é importante, porque num "void" não podemos ter nada. Mas, ai no caso em que ele falou do cast não é lá tão importante não porque em teoria void* e char* são genericos. Mas, para evitar confusões do compilador(e retirar warnings) é sempre bom castar.
[6] Comentário enviado por
ron_lima em 23/05/2004 - 11:40h:
Com a padronização da linguagem pelo comitê ANSI-X3j11, os ponteiros char * deixaram de ser considerados como ponteiros genéricos e a orientação é que utilize-se ponteiros para void. Sem dúvida, a utilização de ponteiros para char pode ser encarada como genérica mas já é um conceito considerado antigo.
No meu comentário, quando eu disse que o cast era importante eu me referia aos casts dentro do for, pois sem eles a operação de incremento de ponteiros gera um erro de compilação. O compilador precisa saber qual o tipo básico do ponteiro para que possa incrementar ou decrementar adequadamente os ponteiros com a utilização dos operadores unários incremento (++) ou decremento (--).
[7] Comentário enviado por
jllucca em 23/05/2004 - 19:02h:
Bem, tenho conhecimento do conceito ser sendo antigo... Mas, isso funciona e no minimo gera um ou dois warnings... tem um problema muito mais grave no seu programa que é não inicializar "i" que nem comentei. Alem disso, se não estou enganado foi C++ que propos essa mudança em C.
[8] Comentário enviado por
ron_lima em 23/05/2004 - 19:51h:
De fato comi uma bola no programinha. Pressa é sempre inimiga da perfeição. Quando à mudança dos ponteiros genéricos para o tipo void realmente foi contemplado pelo comitê X3J11 do ANSI em seu documento X3.159.1989 que descreve todo o padrão da linguagem. Na definição original da linguagem, realmente os ponteiros para char eram considerados ponteiros genéricos. Conforme este trecho do livro de Brian Kernighan e Dennis Ritchie, os inventores da linguagem: "A principal mudança no ANSI C é tornar explícitas as regras sobre como os apontadores podem ser manipulados, efetivamente afirmando o que os bons programadores já praticam e bons compiladores já forçam. Além disso, o tipo void * (apontador para void) substitui o char * como tipo apropriado para um apontador genérico".
O documento a que se refere, que padroniza o C++ nada tem a ver com isso, mesmo por que o C++ foi padronizado por outro comitê, o X3J16, que publicou o documento final de padrão da linguagem C++ somente em 1998.
Por favor, não estou dizendo que seu artigo está errado. Em verdade é um bom artigo e tentei apenas contribuir com alguns comentários.
[9] Comentário enviado por
jllucca em 23/05/2004 - 23:32h:
Eu compreendo, mas mesmo assim tenho que tentar defender meu ponto de vista não acha?
Sobre o C++ quis dizer que ele foi o primeiro a ter a implementação void* e depois o conselho do ANSI C fez estas alterações pois ainda era char* considerado generico... Não sei bem se isso é verdade... história não é meu forte hehehe ^^
[10] Comentário enviado por
engos em 23/06/2004 - 16:26h:
Acho que o pessoal já falou alguma coisa, como esse é o primeiro artigo e você deixou claro que vai ter um segundo, vou esperar um pouco para entrar em detalhes.
Apoio sua iniciativa de fazer uma matéria sobre o void, uma vez que o mesmo não é muito utilizado quando não se sabe o que ele pode fazer, entretanto é muito utilizado quando se sabe seu potencial, principalmente (no meu caso que uso muito em transmissão de dados) para cast.
[11] Comentário enviado por
sax0n_m0f0r em 26/09/2006 - 11:31h:
O ponteiro void '*' pode ser atribuído a qualquer tipo de ponteiro.
se não houver memória suficiente para alocar a memória requisitada a função blablabla() retorna um ponteiro nulo; será que delirei ? o_O eueheueheue
[12] Comentário enviado por
f_Candido em 13/10/2007 - 23:37h:
Bem interessante. Nunca tinha parado para estudar o void.
[13] Comentário enviado por
ryonagana em 25/08/2008 - 20:12h:
eu conhecia orem nunca usei
vejo muito disso em acessos de endereços de uma DLL
[14] Comentário enviado por
rubensalves em 15/05/2011 - 17:52h:
como fazer um programa que conte a data o ano e os dias e contar se o ano foi bissesto