2014-11-05 20 views
13

Ho sentito che i puntatori devono essere prima convertiti in null per garantire la coerenza dei valori tra piattaforme diverse e devono utilizzare l'identificatore di formato %p. Perché è e quali sono esattamente i problemi?Utilizzo di puntatori void su piattaforme diverse

int x=100; 
int *pi=&x; 
printf("value of pi is: %p",(void*)pi); 

risposta

13

printf è una funzione variadic e devono essere passati argomenti dei tipi destra. Lo standard dice %p prende void *.

Implicit cast doesn't take place per variadic functions.

Citando N15707.21.6.1 La funzione fprintf

p: L'argomento è un puntatore nullo. Il valore del puntatore è convertito in una sequenza di caratteri di stampa, in un modo definito dall'implementazione.

+0

Si noti che la citazione è sicuramente specifica per POSIX, IIRC lo standard richiede semplicemente che due puntatori diversi abbiano un output specifico di implementazione diverso. –

+0

@MatteoItalia Grazie. Aggiornato. –

+0

Bella citazione, ma in pratica, come potrebbe il fatto che ** il cast implicito non avvenga ** influisce sul valore dell'argomento passato (in altre parole, come può un cast per 'void *' rendere il valore di ' pi' diverso)? –

8

La presentazione interna o la dimensione di tipi di puntatori diversi non è necessariamente la stessa.

Per esempio in un sistema sizeof(void*) possono essere 2, ma sizeof(int*) è 1.

Da printf è funzione di argomenti variabili, non può controllare i tipi di parametri in ingresso. Se hai passato int*, leggerà il numero errato di byte, perché si aspetta void*.

8

p la specifica di conversione in printf richiede un argomento di tipo void *. C dice che se si passa un argomento di un altro tipo la chiamata richiama un comportamento non definito.

Oltre a ciò, non è necessario che gli oggetti puntatore di tipi diversi abbiano la stessa rappresentazione: C non garantisce che ad esempio sizeof (void *) == sizeof (int *). C garantisce solo che void * abbia la stessa rappresentazione dei puntatori ai tipi di carattere.

+0

Non direi "Oltre a questo", ma piuttosto "Ecco perché": se il n. 2 non fosse il caso, non c'erano motivi per il n. Significato, se tutti i puntatori si assomiglino in termini di layout di memoria, non ci sarebbe bisogno di specificare UB per non-'void'' * '. – glglgl

+0

@glglgl Preferisco ancora "oltre a questo" perché oltre a C dicendo che * I puntatori ad altri tipi non hanno bisogno della stessa rappresentazione o requisiti di allineamento * c'è una specifica regola C per le funzioni di 'fprintf' che dice l'argomento per' p' deve essere un puntatore 'void *'. – ouah

+0

Hai ragione, ma l'interconnessione tra i due rimane. – glglgl

Problemi correlati