void* é mau!

Vou abrir meu coração a voces. Sempre fui amigo dovoid* , quando dava eu usava ele. Ele é muito massa! Aceita qualquer coisa! Nada de ficar se preocupando com tipos. Queres criar um tipo genérico, uma lista, um hash, árvore… cria um struct contendo um campo “void *content”. Beleza, o content apontará para o dado! Muito bom para casos genéricos. Para ver uma implementação muito boa de listas, veja no source do kernel do linux em include/linux/list.h .

Vamos agora supor, que tens uma estrutura de uma árvore e 3 tipos diferentes: “leaf_t“, “internal_node_t” e “tree_t“. E cada um deles tem um ponteiro para o “pai” deles, onde cada item poderia ser “filho” da própria raiz da árvore (tree_t) ou de um nó interno (internal_node_t). Isto não é uma implementação de uma árvore binária padrão, mas uma árvore filogenética com algumas pecularidades.

Poderias colocar um item na estrutura desses items chamado “void *parent“. Mas aí que está a cagada! Esse campo pode receber *qualquer* valor que o compilador não irá reclamar, no máximo dar um warning quando não se tratar de ponteiros. Uma solução melhor seria usar um:

union {
internal_node_t *internal_node;
tree_t *tree;
} parent;

A *grande* diferença entre usar um union com os possíveis valores e um “void *” é: o compilador verificará as atribuições de valores ao union, enquanto com um “void *“, ele o ignora-la, porque o “void *” é mau e não se importa com nada &:-)

Ainda há outras formas de evitar o void * , mas de forma geral, quando for algo muito genérico, realmente “qualquer coisa” pode ser atribuída ali, use o void *, caso contrário, use um union com os tipos definidos. Alias, é importante que os tipos do union neste caso sejam todos ponteiros, desta forma o union inteiro ocupará o mesmo espaço na memória que um void *.  Ou seja, quando o conjunto de possiveis tipos é finito, use union com eles, caso contrário, boa sorte e muito cuidado com o void *.

One thought on “void* é mau!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s