Modo corretto di dichiarare le variabili del puntatore in C / C ++ [chiuso]


91

Ho notato che alcune persone usano la seguente notazione per dichiarare le variabili del puntatore.

(a) char* p;

invece di

(b) char *p;

Io uso (b). Qual è il razionale dietro la notazione (a)? La notazione (b) ha più senso per me perché il puntatore a caratteri non è un tipo in sé. Invece il tipo è carattere e la variabile può essere un puntatore al carattere.

char* c;

Sembra che ci sia un tipo char * e la variabile c sia di quel tipo. Ma in realtà il tipo è char e * c (la posizione di memoria indicata da c) è di quel tipo (char). Se dichiari più variabili contemporaneamente, questa distinzione diventa ovvia.

char* c, *d;

Questo sembra strano. Sia c che d sono lo stesso tipo di puntatori che puntano a un carattere. In questo dal prossimo sembra più naturale.

char *c, *d;

Grazie.


7
Cosa intendi per char pointer non è un tipo? Stai dicendo che un puntatore non è un tipo?
Benjamin Lindley

1
Credo che sia una questione di preferenza a meno che tu non stia guardando una particolare guida di stile (cioè la tua azienda potrebbe avere un certo standard di codifica che devi seguire). Tendo a confonderlo tra la scelta be un po 'nel mezzo. A volte non mi sento a posto char *t, quindi potrei farlo char * t;invece. Tuttavia, ho anche visto spesso char* t;.
RageD

1
Inoltre, il tuo ragionamento "il tipo è char e * c (la posizione di memoria indicata da c) è di quel tipo (char)" sembrerebbe indicare che c'è un carattere dichiarato, mentre in realtà non c'è. Se viene trattato come tale, come a volte lo è dai principianti, porterà sicuramente a violazioni dell'accesso alla memoria.
Benjamin Lindley

1
Entrambi sono ancora sufficientemente descrittivi, (b) mostra che * p è di tipo chare (a) mostra che p è apointer to a char
A Person

1
Con oltre un decennio di esperienza nel settore, oggi è stata la prima volta che questo è venuto fuori, e solo leggendo articoli di altri professionisti del settore. Ovviamente, quindi, non ho mai avuto una conversazione religiosa su questi argomenti come ho avuto con tabs v spazi, commenti di def o dec, o qualsiasi altro argomento "è bello non avere niente di più importante su cui discutere" . Questa è la mia prospettiva, ho preferito, così tardi nel gioco della mia carriera, andare con "char * p" il più delle volte. Sì, spazio prima, spazio dopo. Per lo più, trovo che riduce i bug, in quanto rende il puntatore più ovvio.
Kit10

Risposte:


102

Bjarne Stroustrup ha detto:

La scelta tra "int * p;" e "int * p;" non si tratta di giusto e sbagliato, ma di stile ed enfasi. C ha sottolineato le espressioni; le dichiarazioni erano spesso considerate poco più che un male necessario. Il C ++, d'altra parte, ha una forte enfasi sui tipi.

Un "tipico programmatore C" scrive "int * p;" e lo spiega "* p è ciò che è int" sottolineando la sintassi, e può puntare alla grammatica della dichiarazione C (e C ++) per sostenere la correttezza dello stile. In effetti, * si lega al nome p nella grammatica.

Un "tipico programmatore C ++" scrive "int * p;" e spiega che "p è un puntatore a un tipo di enfasi int". In effetti il ​​tipo di p è int *. Preferisco chiaramente questa enfasi e la vedo come importante per utilizzare bene le parti più avanzate di C ++.

Fonte: http://www.stroustrup.com/bs_faq2.html#whitespace

Consiglierei il secondo stile perché nella situazione in cui stai dichiarando più puntatori in una singola riga (il tuo 4 ° esempio), avere l'asterisco con la variabile sarà quello a cui sei abituato.


34
Altri consigliano di non dichiarare mai più oggetti nella stessa dichiarazione. :-)
Bo Persson

5
Sottolineo la logica alla base della sintassi, quindi preferisco :, che int *psignifica: quando pviene dereferenziato ottengo un int. Quindi più dichiarazioni separate da hanno ,senso: int *p, *q, r(quando po qviene dereferenziato ottengo un int, quando rviene fatto riferimento ottengo un int). Inoltre, la sintassi del puntatore alla funzione ha senso: int (*f)()(quando fviene dereferenziato e chiamato ottengo un int). E questo ha un senso: int *p, (*f)().
Druesukker

2
Questo mi ha aiutato a capire che c'è validità dall'altra parte dell'argomento. Essendo, principalmente, un programmatore di alto livello, sottolineo il tipo; e preferisci int*. Per me, int *p, (*f)()non ha molto senso, ma posso vedere come sarebbe per alcune persone in alcune situazioni.
Assimilater

1
@Druesukker, la tua affermazione ha più senso di quanto sopra, credo.
Muntashir Akon

1
@Druesukker Ma la logica non funziona esattamente per void*(e non funziona affatto per i riferimenti C ++).
jamesdlin

57

Personalmente preferisco posizionare il *con il resto del tipo

char* p;  // p is a pointer to a char.

La gente sosterrà "ma poi char* p, q;diventa fuorviante", a cui dico, "quindi non farlo".


Ottimo argomento per il carattere * p; scelta :) Non mi dispiace nessuno di loro finché non diventa difficile da leggere come l'esempio che hai mostrato, nel qual caso non dovrebbero farlo.
Jesus Ramos

1
E quando vuoi emettere il valore? Lo fai cout << *p;. Allora perché non mettere la stella prima p durante la dichiarazione *p:? Secondo me sarebbe meno confuso.
user1170330

13
@ user1170330, Perché in una volta fa parte della definizione del tipo ed è un operatore di dereferenziazione nell'altro. Nessuna relazione. Semmai, è un bene che abbiano un aspetto diverso, poiché cose diverse dovrebbero apparire diverse.
ikegami

32

Non ci sono differenze nel modo di scrivere. Ma se vuoi dichiarare due o più puntatori in una riga meglio usare la variante (b), perché è chiaro quello che vuoi. Guarda sotto:

int *a;
int* b;      // All is OK. `a` is pointer to int ant `b` is pointer to int
char *c, *d; // We declare two pointers to char. And we clearly see it.
char* e, f;  // We declare pointer `e` and variable `f` of char type.
             // Maybe here it is mistake, maybe not. 
// Better way of course is use typedef:
typedef char* PCHAR;
PCHAR g, h;  // Now `g` and `h` both are pointers.
// If we used define construction for PCHAR we'd get into problem too.

5
typedefnon è un modo migliore "ovviamente". Alcune persone potrebbero preferirlo, ma è problematico se ci sono più persone che lavorano con il tuo codice. Se non ci sono abituato PCHAR, potrei scrivere qualcosa di simile PCHAR *p;, che sarebbe un char**e non quello che intendo. In generale, se vuoi un char**, dovresti scrivere PCHAR*o definire un nuovo tipo, e poi inizia a diventare stupido.
BlackJack

3
Se è necessario un tipo di puntatore complesso come il puntatore alla funzione, è molto buona idea creare typedef. In questo caso rendono il codice molto più semplice. D'altra parte, l'uso di PCHAR è un esempio più sintetico della pratica quotidiana. Ma chiaramente fa quello che vuoi. e poi inizia a diventare stupido Per favore indirizza tutti i reclami a Stroustrup :-)
George Gaál

Se hai scritto PCHAR * p per definire un puntatore a char, sarebbe ovvio che non sai cosa stai facendo e non hai letto il tipo def. La risposta è secondo lui. C'è un altro vantaggio per il typedef; in C è sui modi semplici per rendere le cose opache. pubblicamente avere il simbolo definito come VOID ptr, privatamente il tipo def è qualcos'altro ... Preferisco regolare un typedef una volta ogni tanto e poi aggiustare tutto nel codice quando cambiamo qualcosa su uno dei tipi ... ma C ++ 11 risolve gran parte di questo con auto
UpAndAdam

Per qualcuno che sta solo cercando di tornare a giocare con il C ++ cinque anni dopo il college, questa è una delle migliori risposte.
Panzercrisis

10

Il compromesso è

char * p;

K&R utilizza

char *p;

Dipende da te a meno che tu non stia seguendo uno standard di codifica: in tal caso, dovresti seguire ciò che fanno tutti gli altri.


4
Ho imparato a mie spese che char * x, y non significa che y sia un char *. Ora posso capire perché K&R segue questo stile.
Rahul Kadukar

cos'è K&R e perché è importante quale singola fonte di codice utilizza? Io uso char* p;. è una questione di stile, non di convenzioni o regole. per me ha più senso che p sia di tipo char*, quindi ovviamente * dovrebbe essere con il tipo.
FalcoGer

@FalcoGer Ho aggiunto un collegamento per K&R. Non importa quale sia una singola fonte di codice utilizzata. Il tuo team potrebbe arrabbiarsi con te se non segui i loro standard perché li stai facendo lavorare di più per capire il tuo codice. In questi giorni, spero che le squadre utilizzino clang-formatcomunque.
jnnnnn

2

È tutta una questione di preferenza, personalmente sui progetti che vedo il carattere * tendo a dichiarare più puntatori su righe separate. Non esiste un vero modo "corretto" per farlo e tutto dipende dalle preferenze. Alcuni dicono che è più facile leggere (a) mentre altri dicono che (b) è più facile dichiarare più variabili dello stesso tipo sulla stessa riga.

Trovo che (b) sia più comune e in alcuni casi ho visto

char * a;

o qualcosa del genere. Ancora una volta la preferenza. Qualunque cosa ti trovi a tuo agio o qualunque cosa usi il progetto su cui sto lavorando, userò (a meno che non lo scrivo io stesso, nel qual caso uso (a))

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.