É possível desreferenciar um ponteiro nulo sem conversão de tipo na linguagem de programação C?
Além disso, existe alguma maneira de generalizar uma função que possa receber um ponteiro e armazená-la em um ponteiro vazio e, usando esse ponteiro vazio, podemos criar uma função generalizada?
por exemplo:
void abc(void *a, int b)
{
if(b==1)
printf("%d",*(int*)a); // If integer pointer is received
else if(b==2)
printf("%c",*(char*)a); // If character pointer is received
else if(b==3)
printf("%f",*(float*)a); // If float pointer is received
}
Eu quero tornar essa função genérica sem usar instruções if-else - isso é possível?
Além disso, se houver bons artigos na Internet que expliquem o conceito de ponteiro nulo, seria benéfico se você pudesse fornecer os URLs.
Além disso, é possível aritmética de ponteiro com ponteiros nulos?
fonte
void *
ponteiros da mesma formachar *
, mas não é padrão e você não deve confiar nisso.Em C, a
void *
pode ser convertido em um ponteiro para um objeto de um tipo diferente sem uma conversão explícita:Isso não ajuda a escrever sua função de uma maneira mais genérica.
Você não pode desreferenciar um
void *
com a conversão para um tipo de ponteiro diferente, pois desreferenciar um ponteiro está obtendo o valor do objeto apontado. Um nuvoid
não é um tipo válido; portanto,void *
não é possível desmarcá-lo .A aritmética do ponteiro trata da alteração dos valores do ponteiro por múltiplos dos
sizeof
objetos apontados. Novamente, porvoid
não ser um tipo verdadeiro,sizeof(void)
não tem significado, portanto a aritmética do ponteiro não é válidavoid *
. (Algumas implementações permitem, usando a aritmética equivalente do ponteiro parachar *
.)fonte
void abc(void *a, int b)
. Mas por que não usarvoid abc(int *a, int b)
, já que em sua função você finalmente definiráint *test = a;
, ela salvará uma variável e não vejo outras vantagens definindo outra variável. Vejo muitos códigos gravados dessa maneira usandovoid *
como parâmetros e lançando variáveis posteriormente na função. Mas como essa função é escrita pelo autor, ele deve conhecer o uso da variável; portanto, por que usarvoid *
? ObrigadoVocê deve estar ciente de que em C, diferente de Java ou C #, não há absolutamente nenhuma possibilidade de "adivinhar" com êxito o tipo de objeto
void*
apontado por um ponteiro. Algo semelhante agetClass()
simplesmente não existe, já que essas informações não podem ser encontradas. Por esse motivo, o tipo de "genérico" que você procura sempre vem com metainformação explícita, comoint b
no exemplo ou na string de formato naprintf
família de funções.fonte
Um ponteiro nulo é conhecido como ponteiro genérico, que pode se referir a variáveis de qualquer tipo de dados.
fonte
Até agora, meu entendimento sobre o ponteiro nulo é o seguinte.
Quando uma variável de ponteiro é declarada usando a palavra-chave void - ela se torna uma variável de ponteiro de uso geral. O endereço de qualquer variável de qualquer tipo de dados (char, int, float etc.) pode ser atribuído a uma variável de ponteiro nulo.
Como outro ponteiro de tipo de dados pode ser atribuído ao ponteiro nulo, usei-o na função absolut_value (código mostrado abaixo). Para fazer uma função geral.
Eu tentei escrever um código C simples que toma inteiro ou flutua como argumento e tenta torná-lo positivo, se negativo. Eu escrevi o seguinte código,
Mas eu estava tendo erro, então cheguei a saber que meu entendimento com o ponteiro nulo não está correto :(. Então agora vou avançar para coletar pontos por que isso acontece.
As coisas que eu preciso entender mais sobre ponteiros nulos é isso.
Precisamos converter a variável void pointer para desreferenciá-la. Isso ocorre porque um ponteiro nulo não possui um tipo de dados associado a ele. Não há como o compilador saber (ou adivinhar?) Que tipo de dados é apontado pelo ponteiro nulo. Portanto, para pegar os dados apontados por um ponteiro nulo, nós o compilamos com o tipo correto de dados contidos no local dos ponteiros nulos.
Um ponteiro nulo pode ser realmente útil se o programador não tiver certeza sobre o tipo de dado inserido pelo usuário final. Nesse caso, o programador pode usar um ponteiro nulo para apontar para o local do tipo de dados desconhecido. O programa pode ser configurado de forma a solicitar ao usuário que informe o tipo de dados e a conversão do tipo pode ser realizada de acordo com as informações inseridas pelo usuário. Um trecho de código é fornecido abaixo.
Outro ponto importante que você deve ter em mente sobre os ponteiros nulos é que - a aritmética do ponteiro não pode ser executada em um ponteiro nulo.
Então agora eu entendi qual foi o meu erro. Estou corrigindo o mesmo.
Referências :
http://www.antoarts.com/void-pointers-in-c/
http://www.circuitstoday.com/void-pointers-in-c .
O novo código é como mostrado abaixo.
Obrigado,
fonte
Não, não é possível. Que tipo o valor não referenciado deve ter?
fonte
fonte
printf
. Esta resposta tem um bom exemplo disso.int b
por um enum, mas fazer qualquer alteração posterior nesse enum interromperia essa função.A única maneira simples que vejo é usar a sobrecarga .. que não está disponível no idioma de programação C AFAIK.
Você considerou o idioma de programação C ++ para o seu programa? Ou existe alguma restrição que proíba seu uso?
fonte
Aqui está um breve ponteiro sobre
void
ponteiros: https://www.learncpp.com/cpp-tutorial/613-void-pointers/Supondo que a memória da máquina seja endereçável por byte e não exija acessos alinhados, a maneira mais genérica e atômica (mais próxima da representação no nível da máquina) de interpretar a
void*
é como um ponteiro para um byteuint8_t*
. Converter umvoid*
para auint8_t*
permitiria, por exemplo, imprimir os primeiros 1/2/4/8 / quantos você desejar, começando nesse endereço, mas você não pode fazer muito mais.fonte
Você pode imprimir facilmente uma impressora vazia
fonte
void
tem o mesmo tamanho queint
?void
, isso não está imprimindo um ponteiro, mas simint
no endereço de memória que o ponteiro contém (que nesse caso seria o valor dep
).Como C é uma linguagem de tipo estatístico e de tipo forte, você deve decidir o tipo de variável antes da compilação. Ao tentar emular genéricos em C, você tentará reescrever o C ++ novamente, portanto, seria melhor usar o C ++.
fonte
ponteiro nulo é um ponteiro genérico. Endereço de qualquer tipo de dados de qualquer variável pode ser atribuído a um ponteiro nulo.
fonte
Você não pode desreferenciar um ponteiro sem especificar seu tipo, porque tipos de dados diferentes terão tamanhos diferentes na memória, ou seja, um int com 4 bytes, um char com 1 byte.
fonte
Fundamentalmente, em C, "tipos" são uma maneira de interpretar bytes na memória. Por exemplo, qual o código a seguir
Diz "Quando executo main, quero alocar 4 (tamanho do número inteiro) + 4 (tamanho do número inteiro) = 8 (total de bytes) de memória. Quando escrevo '.x' como um lvalue em um valor com o rótulo de tipo Aponte no tempo de compilação, recupere dados do local da memória do ponteiro e mais quatro bytes.Dê ao valor de retorno o rótulo de tempo de compilação "int".
Dentro do computador em tempo de execução, sua estrutura "Ponto" é assim:
E aqui está a
void*
aparência do seu tipo de dados: (assumindo um computador de 32 bits)fonte
Isso não funcionará, mas o void * pode ajudar muito na definição de ponteiro genérico para funções e transmiti-lo como argumento para outra função (semelhante ao retorno de chamada em Java) ou definir uma estrutura semelhante ao oop.
fonte