Hoje, quando eu estava lendo o código de outras pessoas, vi algo como void *func(void* i);
: o que isso void*
significa aqui para o nome da função e para o tipo de variável, respectivamente?
Além disso, quando precisamos usar esse tipo de ponteiro e como usá-lo?
malloc
ecalloc
. A página de manual continua dizendo: "... retorne um ponteiro para a memória alocada, adequadamente alinhada para qualquer tipo de dados interno".Respostas:
Um ponteiro para
void
é um tipo de ponteiro "genérico". Avoid *
pode ser convertido para qualquer outro tipo de ponteiro sem uma conversão explícita. Você não pode desreferenciar umvoid *
ponteiro ou fazer aritmética com ele; você deve convertê-lo em um ponteiro para um tipo de dados completo primeiro.void *
é frequentemente usado em locais onde você precisa trabalhar com diferentes tipos de ponteiros no mesmo código. Um exemplo comumente citado é a função de bibliotecaqsort
:base
é o endereço de uma matriz,nmemb
é o número de elementos na matriz,size
é o tamanho de cada elemento ecompar
é um ponteiro para uma função que compara dois elementos da matriz. É assim chamado:As expressões de matriz
iArr
,dArr
elArr
são convertidos implicitamente a partir de tipos de matriz para tipos de ponteiro na chamada de função, e cada um é implicitamente convertido de "ponteiro aint
/double
/long
" a "ponteiro devoid
".As funções de comparação seriam parecidas com:
Ao aceitar
void *
,qsort
pode trabalhar com matrizes de qualquer tipo.A desvantagem do uso
void *
é que você joga a segurança de tipos pela janela e entra no tráfego que se aproxima. Não há nada para protegê-lo de usar a rotina de comparação errada:compareInt
espera que seus argumentos apontem paraint
s, mas na verdade está trabalhando comdouble
s. Não há como detectar esse problema no momento da compilação; você acabará com uma matriz distorcida.fonte
void*
possa ser convertido em um ponteiro de função. Mas para ponteiros de dados o que você disse é válido.Usar um vazio * significa que a função pode receber um ponteiro que não precisa ser de um tipo específico. Por exemplo, nas funções de soquete, você tem
isso significa que você pode chamá-lo de várias maneiras, por exemplo
fonte
C é notável a esse respeito. Pode-se dizer que o
void
nadavoid*
é tudo (pode ser tudo).É tão pequeno
*
que faz a diferença.René apontou isso. A
void *
é um ponteiro para algum local. O que há como "interpretar" é deixado para o usuário.É a única maneira de ter tipos opacos em C. Exemplos muito importantes podem ser encontrados, por exemplo, em bibliotecas glib ou gerais da estrutura de dados. É tratado muito detalhadamente em "Interfaces e implementações C".
Sugiro que você leia o capítulo completo e tente entender o conceito de um ponteiro para "obtê-lo".
fonte
é um 'ponteiro para a memória sem suposições de que tipo está armazenado'. Você pode usar, por exemplo, se deseja passar um argumento para a função e esse argumento pode ser de vários tipos e, na função, você manipulará cada tipo.
fonte
Você pode dar uma olhada neste artigo sobre ponteiros http://www.cplusplus.com/doc/tutorial/pointers/ e ler o capítulo: ponteiros nulos .
Isso também funciona para a linguagem C.
fonte
Um ponteiro nulo é conhecido como ponteiro genérico. Eu gostaria de explicar com um exemplo de cenário pthread.
A função thread terá o protótipo como
Os designers da API pthread consideraram o argumento e retornam os valores da função do encadeamento. Se essas coisas forem tornadas genéricas, podemos digitar cast para void * enquanto enviamos como argumento. da mesma forma, o valor de retorno pode ser recuperado de void * (mas eu nunca usei valores de retorno da função thread).
fonte
pthread_exit(NULL);
vez dereturn 0;
no final do main?a
void*
é um ponteiro, mas o tipo para o qual ele aponta não é especificado. Quando você passa um ponteiro nulo para uma função, você precisa saber qual era o seu tipo para convertê-lo novamente no tipo correto posteriormente na função para usá-lo. Você verá exemplos empthreads
que funções de uso com exatamente o protótipo em seu exemplo são usadas como a função de thread. Em seguida, você pode usar ovoid*
argumento como um ponteiro para um tipo de dados genérico de sua escolha e, em seguida, convertê-lo novamente nesse tipo para usar na função de encadeamento. Você precisa ter cuidado ao usar ponteiros nulos; a menos que retorne a um ponteiro do seu tipo verdadeiro, você pode acabar com todos os tipos de problemas.fonte
A norma C11 (n1570) §6.2.2.3 al1 p55 diz:
Você pode usar esse ponteiro genérico para armazenar um ponteiro em qualquer tipo de objeto, mas não pode usar operações aritméticas comuns com ele e não pode deferi-lo.
fonte
A função leva um ponteiro para um tipo arbitrário e retorna um desses.
fonte
significa ponteiro, você pode usar este link para obter mais informações sobre o ponteiro http://www.cprogramming.com/tutorial/c/lesson6.html
fonte