2013-06-07 5 views
13

Essendo nuovo di C, l'unico utilizzo pratico che ho ottenuto dai puntatori void è per funzioni versatili che possono memorizzare diversi tipi di dati in un dato puntatore. Pertanto non ho digitato il mio puntatore durante l'allocazione della memoria.Perché digitare cast un puntatore void?

Ho visto alcuni esempi di codice che a volte usano puntatori void, ma ottengono il cast del tipo. Perché è utile? Perché non creare direttamente il tipo di puntatore desiderato invece di un vuoto?

+6

Puoi mostrare un esempio? –

+3

Non è necessario eseguire il cast da 'void *' perché la lingua definisce una conversione automatica da 'void *' a qualsiasi altro tipo di puntatore, ma non tutti i programmatori ne sono a conoscenza (non tutti gli autori di libri C, purtroppo) . –

+0

Devi lanciare un puntatore vuoto se vuoi accedere alla sua struttura. (Struct) –

risposta

6

È necessario lanciare puntatori void a qualcosa d'altro se si vuole dereferenziare loro, per esempio, si ottiene un puntatore nullo come parametro di funzione e si sa per certo che questo è un numero intero:

void some_function(void * some_param) { 
    int some_value = *some_param; /* won't work, you can't dereference a void pointer */ 
} 

void some_function(void * some_param) { 
    int some_value = *((int *) some_param); /* ok */ 
} 
+1

Non è necessario *; a l'approccio più leggibile (preferito da me) è 'int * tmp = param; int val = * tmp; '. –

+0

@ H2CO3 È necessario se il puntatore è di tipo vuoto. Come è nell'esempio di Guillaume. –

+1

@Armin Non è necessario **, ripeto: il cast può essere evitato se si assegna il puntatore a un temporaneo. –

1

tuo vuoto il puntatore può rappresentare un tipo più complicato come una struttura che è necessario effettuare il dereferenziamento per poter accedere ai membri.

typedef struct CombinedData 
{ 
    int memberA; 
    double memberB; 
} CombinedData; 

void fun(void* data) 
{ 
    CombinedData* p = (CombinedData*)data; 
    doSomethingWith(p->memberA, p->memberB);   
} 
+2

Come già detto da altre persone, non è necessario eseguire il cast esplicito dei 'dati' prima dell'assegnazione. Un altro punto è che il tuo codice è rotto per un compilatore * C * (non uno C++): 'CombinedData * p' →' struct CombinedData * p'. – firegurafiku

+1

@firegurafiku Questo è un ottimo punto che aggiornerò il post per utilizzare una struttura tipata. È passato molto tempo da quando ho risposto a questo e non riesco a ricordare se ho notato che era una domanda C e non una C++. – DuncanACoulter

12

Ci sono due ragioni per lanciare un puntatore nullo a un altro tipo in C.

  1. Se si desidera accedere a qualcosa che è puntato dal puntatore (*(int*)p = 42)
  2. Se si è in realtà scrittura di codice nel sottoinsieme comune di C e C++, piuttosto che "reale" C. Vedi anche Do I cast the result of malloc?

la ragione di 1 dovrebbe essere ovvio. Il secondo è perché C++ non consente la conversione implicita da void* ad altri tipi, mentre C lo consente.

+1

Ma l'argomento 2 non è valido: non si dovrebbe compilare il codice C con un compilatore C++. –

+5

@ H2Co3: vero, ma a volte è stato definito il codice nei file di intestazione in macro o funzioni inline che è concepito per essere utilizzabile in entrambi i codici C e C++ che include tali intestazioni. –

+1

@ H2CO3 Tuttavia, alcune persone lo fanno. Stavo cercando di spiegare il fenomeno, non di giustificarlo. – wolfgang