2009-09-24 17 views
5

apertura del codice di base Postgres, vedo che la maggior parte del codice C è scritto da avere puntatori con la -> notation in modo tale che:C e puntatore notazione

(foo)->next = 5; 

so che puntatore notazione ha livelli di precedenza, tali che -> = (* foo). e non è uguale a * foo.

Tuttavia, significa qualcosa quando le parentesi sono al di fuori del nome della variabile e de-referenziare l'indirizzo di prossimo o è semplicemente una convenzione che è endemica per uno stile di codifica?

risposta

6

È una convenzione di codifica che non ho mai visto prima.

Ma non cambia nulla.

(foo)->next = 5; 

è esattamente equivalente a

foo->next = 5; 
+0

Fantastico, grazie. Questo è quello che pensavo, e l'ho trovato particolarmente strano visto che era dappertutto nel codebase. – mduvall

+1

Per espanderlo, il motivo per cui utilizzerai questo costrutto è come una cintura di sicurezza nel caso in cui foo sia una macro. È la stessa ragione per cui alcune guide di stile C (ad esempio FreeBSD) suggeriscono che tutte le dichiarazioni di ritorno siano del modulo return (x); invece di restituire solo x; – Benno

+1

Anche se 'pippo' fosse una macro, sarebbe saggio averlo completamente tra parentesi, ad es. '#define foo (blargity-> blah)' –

1

Non ha senso. Le parentesi non hanno effetto poiché l'espressione al loro interno è così semplice. È fondamentalmente

(*(foo)).next = 5; 

Che, come potete vedere, è un insieme estraneo di parentesi. Se è così che sta andando il progetto, fallo. Altrimenti, penso che sia piuttosto orribile, quindi proverei a non usarlo.

+0

Intendevi ''(* (foo)). next = 5;''? –

+0

Oh. Destra. Almeno ora sento che c'è una ragione per cui non riesco a concentrarmi sui miei compiti. Grazie per avermelo segnalato e grazie a Robert per averlo risolto. –

2

È una convenzione di codifica per la sicurezza.

Nel codice semplice, dove foo è solo un puntatore, i paren sono ridondanti.

(foo)->next = 5; 

Tuttavia, considerare se ci sia o era la possibilità che foo potrebbe essere definito da una macro in modo da è un'espressione più complessa.

In tal caso, potrebbe essere necessario il paren per evitare un errore del compilatore o, peggio, per evitare la precedenza errata. Immaginate se tradotto in un'espressione brutto come:

(++get_foo())->next = 5; 

o un cast comune:

((db_record*)foo_ptr)->next = 5; 

Qualcosa da tenere a mente con idiomatica codice C è che le macro sono stati spesso utilizzati come un meccanismo di astrazione per cose che potremmo fare più esplicitamente in altre lingue ;-)

+0

Qualsiasi macro che _non riesca a parentesi con la sua espansione è un problema. IMHO dovrebbe essere il lavoro della macro per garantire la propria sicurezza d'uso, non il lavoro del macro-chiamante. –