Qual è la differenza tra const int *, const int * const e int const *?


1357

Ho sempre rovinare come utilizzare const int*, const int * conste int const *in modo corretto. Esiste una serie di regole che definiscono cosa puoi e cosa non puoi fare?

Voglio sapere tutte le cose da fare e tutte le cose da non fare in termini di incarichi, passaggio alle funzioni, ecc.


175
È possibile utilizzare la "Regola in senso orario / a spirale" per decodificare la maggior parte delle dichiarazioni C e C ++.
James McNellis,

52
cdecl.org è un ottimo sito Web che traduce automaticamente le dichiarazioni C per te.
Dave Gallagher,

6
@Calmarius: inizia dove il nome-tipo è / dovrebbe essere, muoviti a destra quando puoi, a sinistra quando devi . int *(*)(char const * const). Inizia a destra del tra parentesi *allora dobbiamo spostare a sinistra: pointer. Al di fuori delle parentesi, siamo in grado di spostarsi a destra: pointer to function of .... Poi dobbiamo andare a sinistra: pointer to function of ... that returns pointer to int. Ripetere l'operazione per espandere il parametro (il ...): pointer to function of (constant pointer to constant char) that returns pointer to int. Quale sarebbe l'equivalente dichiarazione di una riga in una lingua di facile lettura come Pascal?
Mark K Cowan,

1
@MarkKCowan In Pascal sarebbe qualcosa di simile function(x:^char):^int. Alcuni tipi di funzione implicano un puntatore a una funzione, quindi non è necessario specificarla e Pascal non applica la correttezza const. Può essere letto da sinistra a destra.
Calmarius,

5
La prima cosa a sinistra della "const" è ciò che è costante. Se "const" è la cosa più lontana a sinistra, allora la prima cosa a destra è ciò che è costante.
Cupcake,

Risposte:


2209

Leggilo all'indietro (come guidato da Clockwise / Spiral Rule ):

  • int* - puntatore a int
  • int const * - puntatore a const int
  • int * const - puntatore const a int
  • int const * const - puntatore const a const int

Ora il primo constpuò essere su entrambi i lati del tipo, quindi:

  • const int * == int const *
  • const int * const == int const * const

Se vuoi impazzire davvero puoi fare cose del genere:

  • int ** - puntatore a puntatore a int
  • int ** const - un puntatore const a un puntatore a un int
  • int * const * - un puntatore a un puntatore const a un int
  • int const ** - un puntatore a un puntatore a una const int
  • int * const * const - un puntatore const a un puntatore const a un int
  • ...

E per essere sicuri che siamo chiari sul significato di const:

int a = 5, b = 10, c = 15;

const int* foo;     // pointer to constant int.
foo = &a;           // assignment to where foo points to.

/* dummy statement*/
*foo = 6;           // the value of a can´t get changed through the pointer.

foo = &b;           // the pointer foo can be changed.



int *const bar = &c;  // constant pointer to int 
                      // note, you actually need to set the pointer 
                      // here because you can't change it later ;)

*bar = 16;            // the value of c can be changed through the pointer.    

/* dummy statement*/
bar = &a;             // not possible because bar is a constant pointer.           

fooè un puntatore variabile a un numero intero costante. Ciò consente di modificare ciò a cui si punta ma non il valore a cui si punta. Molto spesso questo è visto con stringhe in stile C in cui hai un puntatore a const char. È possibile modificare la stringa a cui si punta ma non è possibile modificare il contenuto di queste stringhe. Questo è importante quando la stringa stessa si trova nel segmento di dati di un programma e non deve essere modificata.

barè un puntatore costante o fisso a un valore che può essere modificato. Questo è come un riferimento senza lo zucchero sintattico extra. Per questo motivo, di solito si utilizza un riferimento in cui si utilizza un T* constpuntatore a meno che non sia necessario consentire i NULLpuntatori.


482
Vorrei aggiungere una regola empirica che può aiutarti a ricordare come scoprire se 'const' si applica al puntatore o ai dati appuntiti: dividi l'istruzione al segno asterix, quindi, se la parola chiave const appare nella parte sinistra (come in 'const int * foo') - appartiene ai dati appuntiti, se è nella parte giusta ('int * const bar') - riguarda il puntatore.
Michael,

14
@Michael: Complimenti a Michael per una regola così semplice per ricordare / comprendere la regola const.
sivabudh,

10
@Jeffrey: leggerlo all'indietro funziona bene finché non ci sono parentesi. Quindi, beh ... usa typedefs
Mooing Duck,

12
+1, anche se un riassunto migliore sarebbe: leggere le dichiarazioni dei puntatori all'indietro , ciò significa, vicino alla dichiarazione di @Michael: interrompere la normale lettura da sinistra a destra al primo asterisco.
Lupo,

3
@gedamial lo fa, funziona benissimo, ma devi assegnarlo nello stesso momento in cui lo dichiari (perché non puoi riassegnare un "puntatore const"). const int x = 0; const int *const px = &x; const int *const *const p = &px;funziona benissimo.
RastaJedi

357

Per coloro che non conoscono la regola in senso orario / a spirale: inizia dal nome della variabile, sposta in senso orario (in questo caso, vai indietro) al puntatore o al tipo successivo . Ripeti fino al termine dell'espressione.

Ecco una demo:

puntatore a int

puntatore const a int const

puntatore a int const

puntatore a const int

puntatore const a int


8
@Jan il link per l'esempio complesso non ha autorizzazioni. puoi pubblicarlo direttamente qui o rimuovere le restrizioni di visualizzazione?
R71,

8
@Rog aveva tutte le autorizzazioni di accesso aperte ... Non ho scritto l'articolo e purtroppo non ho le autorizzazioni di accesso. Tuttavia, ecco una versione archiviata dell'articolo che funziona ancora: archive.is/SsfMX
Jan Rüegg

8
L'esempio complesso è ancora da destra a sinistra, ma include la risoluzione delle parentesi come si farebbe normalmente. L'intera spirale in senso orario non lo rende più facile.
Matteo Leggi il

4
Esempio void (*signal(int, void (*fp)(int)))(int);
supremo

3
Non fare affidamento su questa regola. Questo non è universale. Ci sono alcuni casi in cui fallisce.
Hawcks,

150

Penso che a tutto sia già stata data una risposta, ma voglio solo aggiungere che dovresti stare attento a typedefs! NON sono solo sostituzioni di testo.

Per esempio:

typedef char *ASTRING;
const ASTRING astring;

Il tipo di astringè char * const, no const char *. Questo è uno dei motivi che tendo sempre a mettere consta destra del tipo e mai all'inizio.


20
E per me questo è il motivo per non scrivere mai i puntatori. Non vedo il vantaggio in cose del genere typedef int* PINT(presumo sia qualcosa derivato dalle pratiche in C e molti sviluppatori hanno continuato a farlo). Fantastico, l'ho sostituito *con un P, non accelera la digitazione, oltre a introdurre il problema menzionato.
Mephane,

1
@Mephane - Posso vederlo. Tuttavia, a me sembra un po 'indietro per evitare una bella funzione linguistica per continuare a usare una regola sintattica eccezionale (sul posizionamento "const"), piuttosto che evitare di usare la regola sintattica eccezionale in modo da poter tranquillamente utilizzare questa funzione linguistica .
TED

6
@Mephane PINTè davvero un uso piuttosto stupido di un typedef, soprattutto perché mi fa pensare che i negozi di sistema utilizzino la birra per la memoria. i typedef sono piuttosto utili per gestire i puntatori alle funzioni.
avvicina

5
@KazDragon GRAZIE! Senza di essa, avrei fatto un casino con tutte quelle cose dattiloscritte PVOID, LPTSTRin Win32 API!
David Lee,

2
@Mephane: ho dovuto usare pSomething un paio di volte quando utilizzavo alcune macro legacy che erano state scritte per accettare un tipo, ma si sarebbero spezzate se il tipo non fosse un singolo identificatore alfanumerico. :)
Groo

56

Come praticamente tutti hanno sottolineato:

Qual è la differenza tra const X* p, X* const pe const X* const p?

Devi leggere le dichiarazioni dei puntatori da destra a sinistra.

  • const X* p significa "p indica una X che è const": l'oggetto X non può essere modificato tramite p.

  • X* const p significa "p è un puntatore const a una X che non è const": non puoi cambiare il puntatore p stesso, ma puoi cambiare l'oggetto X tramite p.

  • const X* const p significa "p è un puntatore const a una X che è const": non puoi cambiare il puntatore p stesso, né puoi cambiare l'oggetto X tramite p.


3
Non dimenticare che const X* p;== X const * p;come in"p points to an X that is const": the X object can't be changed via p.
Jesse Chisholm il

spiegazione semplice e piacevole!
Edison Lo,

50
  1. Riferimento costante:

    Un riferimento a una variabile (qui int), che è costante. Passiamo la variabile principalmente come riferimento, perché i riferimenti hanno dimensioni inferiori rispetto al valore reale, ma c'è un effetto collaterale e questo perché è come un alias della variabile effettiva. Potremmo cambiare accidentalmente la variabile principale attraverso il nostro pieno accesso all'alias, quindi rendiamo costante per prevenire questo effetto collaterale.

    int var0 = 0;
    const int &ptr1 = var0;
    ptr1 = 8; // Error
    var0 = 6; // OK
  2. Puntatori costanti

    Una volta che un puntatore costante punta a una variabile, non può puntare a nessuna altra variabile.

    int var1 = 1;
    int var2 = 0;
    
    int *const ptr2 = &var1;
    ptr2 = &var2; // Error
  3. Puntatore a costante

    Un puntatore attraverso il quale non è possibile modificare il valore di una variabile che punta è noto come puntatore a costante.

    int const * ptr3 = &var2;
    *ptr3 = 4; // Error
  4. Puntatore costante a una costante

    Un puntatore costante a una costante è un puntatore che non può né cambiare l'indirizzo a cui punta e né può cambiare il valore mantenuto a quell'indirizzo.

    int var3 = 0;
    int var4 = 0;
    const int * const ptr4 = &var3;
    *ptr4 = 1;     // Error
     ptr4 = &var4; // Error

20

La regola generale è che la constparola chiave si applica a ciò che la precede immediatamente. Eccezione, un inizio si constapplica a quanto segue.

  • const int*è uguale int const*e significa "puntatore a costante int" .
  • const int* constè lo stesso di int const* conste significa "puntatore costante a costante int" .

Modifica: Per il Dos and Do n't , se questa risposta non è sufficiente, potresti essere più preciso su ciò che vuoi?


19

Questa domanda mostra esattamente perché mi piace fare le cose nel modo in cui ho menzionato nella mia domanda è const dopo id di tipo accettabile?

Insomma, trovo il modo più semplice per ricordare la regola è che il "const" va dopo la cosa si applica a. Quindi nella tua domanda "int const *" significa che int è costante, mentre "int * const" significherebbe che il puntatore è costante.

Se qualcuno decide di metterlo in primo piano (ad esempio: "const int *"), come un'eccezione speciale in quel caso si applica alla cosa dopo di essa.

Molte persone amano usare quella speciale eccezione perché pensano che sia più bella. Non mi piace, perché è un'eccezione, e quindi confonde le cose.


2
Sono lacerato su questo problema. Logicamente ha senso. Tuttavia la maggior parte degli sviluppatori di c ++ scriverà const T*ed è diventato più naturale. Quante volte usi mai a T* const, comunque un riferimento andrà bene. Mi è capitato un po 'di tutto questo quando volevo un boost::shared_ptr<const T>e invece ho scritto const boost::shared_ptr<T>. Stesso problema in un contesto leggermente diverso.
Matt Price,

In realtà, utilizzo puntatori costanti più spesso di quanto non utilizzi costanti. Inoltre, devi pensare a come reagirai in presenza di puntatori a puntatori (ecc.) Certo, quelli sono più rari, ma sarebbe bello pensare alle cose in un modo in cui puoi gestire queste situazioni con applomb.
TED,

1
L'altro bel vantaggio di posizionare la const a destra del tipo è che ora tutto alla sinistra di qualunque constè il tipo di ciò che è const, e tutto alla sua destra è ciò che è in realtà const. Prendi int const * const * p;come esempio. No, di solito non scrivo così, questo è solo un esempio. Primo const: digitare int, e l'int che è const è il contenuto del puntatore const che è il contenuto di p. Seconda const: type è puntatore a constint, const oblect è il contenuto dip
dgnuff

18

Uso semplice di const.

L'uso più semplice è dichiarare una costante con nome. Per fare ciò, si dichiara una costante come se fosse una variabile ma si aggiunge constprima di essa. Uno deve inizializzarlo immediatamente nel costruttore perché, ovviamente, non è possibile impostare il valore in un secondo momento poiché ciò lo altererebbe. Per esempio:

const int Constant1=96; 

creerà una costante intera, chiamata senza fantasia Constant1, con il valore 96.

Tali costanti sono utili per i parametri utilizzati nel programma ma non devono essere modificati dopo la compilazione del programma. Ha un vantaggio per i programmatori rispetto al #definecomando preprocessore C in quanto è compreso e utilizzato dal compilatore stesso, non solo sostituito nel testo del programma dal preprocessore prima di raggiungere il compilatore principale, quindi i messaggi di errore sono molto più utili.

Funziona anche con i puntatori, ma bisogna fare attenzione consta determinare se il puntatore o ciò a cui punta è costante o entrambi. Per esempio:

const int * Constant2 

dichiara che Constant2è un puntatore variabile a un numero intero costante e:

int const * Constant2

è una sintassi alternativa che fa lo stesso, mentre

int * const Constant3

dichiara che Constant3è puntatore costante a un intero variabile e

int const * const Constant4

dichiara che Constant4è puntatore costante a un numero intero costante. Fondamentalmente 'const' si applica a tutto ciò che è alla sua sinistra immediata (tranne se non c'è nulla nel qual caso si applica a qualunque sia il suo diritto immediato).

rif: http://duramecho.com/ComputerInformation/WhyHowCppConst.html


9

Ho avuto gli stessi dubbi su di te fino a quando non mi sono imbattuto in questo libro del Guru Scott Meyers del C ++. Fai riferimento al terzo articolo di questo libro in cui parla in dettaglio dell'uso const.

Segui questo consiglio

  1. Se la parola constappare a sinistra dell'asterisco, ciò che viene indicato è costante
  2. Se la parola constappare a destra dell'asterisco, il puntatore stesso è costante
  3. Se constappare su entrambi i lati, entrambi sono costanti

7

È semplice ma difficile. Si prega di notare che possiamo scambiare la constqualificazione con qualsiasi tipo di dati ( int, char, float, etc.).

Vediamo gli esempi seguenti.


const int *p==> *pè di sola lettura [ pè un puntatore a un numero intero costante]

int const *p==> *pè di sola lettura [ pè un puntatore a un numero intero costante]


int *p const==> Dichiarazione errata . Il compilatore genera un errore di sintassi.

int *const p==> pè di sola lettura [ pè un puntatore costante a un numero intero]. Poiché il puntatore pqui è di sola lettura, la dichiarazione e la definizione devono trovarsi nello stesso posto.


const int *p const ==> Dichiarazione errata . Il compilatore genera un errore di sintassi.

const int const *p ==> *pè di sola lettura

const int *const p1 ==> *pe psono di sola lettura [ pè un puntatore costante a un numero intero costante]. Poiché il puntatore pqui è di sola lettura, la dichiarazione e la definizione devono trovarsi nello stesso posto.


int const *p const ==> Dichiarazione errata . Il compilatore genera un errore di sintassi.

int const int *p ==> Dichiarazione errata . Il compilatore genera un errore di sintassi.

int const const *p ==> *pè di sola lettura ed è equivalente aint const *p

int const *const p ==> *pe psono di sola lettura [ pè un puntatore costante a un numero intero costante]. Poiché il puntatore pqui è di sola lettura, la dichiarazione e la definizione devono trovarsi nello stesso posto.


6

Ci sono molti altri punti sottili che circondano la correttezza const in C ++. Suppongo che la domanda qui sia stata semplicemente su C, ma darò alcuni esempi correlati poiché il tag è C ++:

  • Spesso si passano argomenti di grandi dimensioni come le stringhe in quanto TYPE const &impedisce all'oggetto di essere modificato o copiato. Esempio :

    TYPE& TYPE::operator=(const TYPE &rhs) { ... return *this; }

    Ma non ha TYPE & constsenso perché i riferimenti sono sempre costanti.

  • È sempre necessario etichettare i metodi di classe che non modificano la classe come const, altrimenti non è possibile chiamare il metodo da un TYPE const &riferimento. Esempio :

    bool TYPE::operator==(const TYPE &rhs) const { ... }

  • Esistono situazioni comuni in cui sia il valore di ritorno che il metodo devono essere const. Esempio :

    const TYPE TYPE::operator+(const TYPE &rhs) const { ... }

    In effetti, i metodi const non devono restituire i dati di classe interni come riferimento a non-const.

  • Di conseguenza, si deve spesso creare sia un metodo const che un metodo non const utilizzando il sovraccarico const. Ad esempio, se lo definisci T const& operator[] (unsigned i) const;, probabilmente vorrai anche la versione non const data da:

    inline T& operator[] (unsigned i) { return const_cast<char&>( static_cast<const TYPE&>(*this)[](i) ); }

Dopotutto, non ci sono funzioni const in C, le funzioni non membri non possono esse stesse essere costanti in C ++, i metodi const potrebbero avere effetti collaterali e il compilatore non può usare le funzioni const per evitare duplicati di funzioni. In effetti, anche un semplice int const &riferimento potrebbe testimoniare che il valore a cui si riferisce è cambiato altrove.


6

La sintassi della dichiarazione C e C ++ è stata ripetutamente descritta come un esperimento fallito, dai progettisti originali.

Invece, diamo il nome del tipo “puntatore a Type”; Lo chiamerò Ptr_:

template< class Type >
using Ptr_ = Type*;

Ora Ptr_<char>è un puntatore a char.

Ptr_<const char>è un puntatore a const char.

Ed const Ptr_<const char>è un constpuntatore a const char.

Là.

inserisci qui la descrizione dell'immagine


3
hai un preventivo per la prima frase?
sp2danny,

@ sp2danny: Googling "Esperimento fallito nella sintassi C" non fa che tirar fuori una serie di interviste con Bjarne Stroustrup, dove esprime la sua opinione in quella direzione, ad esempio "Considero la sintassi del dichiarante C un esperimento fallito" nell'intervista di Slashdot. Quindi non ho alcun riferimento per l'affermazione sui punti di vista dei progettisti originali di C. Immagino che possa essere trovato da uno sforzo di ricerca sufficientemente forte, o forse confutato semplicemente chiedendoli, ma penso che sia meglio così com'è adesso. con quella parte del reclamo, ancora indecisa e probabilmente vera :)
Saluti e hth. - Alf

1
"La sintassi della dichiarazione C e C ++ è stata ripetutamente descritta come un esperimento fallito, dai progettisti originali." sbagliato per C si prega di cambiare la frase su C o fornire alcune citazioni.
Stargateur

3
@Stargateur: A quanto pare hai letto i commenti precedenti e hai trovato qualcosa che potresti sfruttare per la pedanteria. Buona fortuna con la tua vita. Ad ogni modo, i vecchi come me ricordano molto che non possiamo provare senza impegnarci in ricerche che richiedono molto tempo. Potresti semplicemente prendere la mia parola.
Saluti e hth. - Alf


6

Per me, la posizione, constovvero se appare a SINISTRA o A DESTRA o sia a SINISTRA che A DESTRA rispetto a ciò *mi aiuta a capire il significato reale.

  1. UN const a SINISTRA di *indica che l'oggetto puntato dal puntatore è un constoggetto.

  2. UN const a DESTRA di *indica che il puntatore è un constpuntatore.

La seguente tabella è tratta dal lettore di corsi del laboratorio di programmazione C ++ standard Stanford CS106L.

inserisci qui la descrizione dell'immagine


3

Questo riguarda principalmente la seconda riga: migliori pratiche, assegnazioni, parametri di funzione ecc.

Pratica generale. Prova a fare tutto il constpossibile. O, per dirla in un altro modo, fai tutto constper cominciare, quindi rimuovi esattamente il set minimo di consts necessario per consentire al programma di funzionare. Questo sarà di grande aiuto nel raggiungimento della correttezza const e contribuirà a garantire che i bug sottili non vengano introdotti quando le persone cercano di assegnare in cose che non dovrebbero modificare.

Evita const_cast <> come la peste. Esistono uno o due casi d'uso legittimi, ma sono molto pochi e distanti tra loro. Se stai cercando di cambiare un constoggetto, farai molto meglio per trovare chiunque lo abbia dichiarato constal primo passo e discutere la questione con loro per raggiungere un consenso su cosa dovrebbe accadere.

Il che porta molto bene agli incarichi. Puoi assegnare qualcosa solo se non è const. Se vuoi assegnare qualcosa che è const, vedi sopra. Ricorda che nelle dichiarazioni int const *foo;e int * const bar;cose diverse lo sonoconst - altre risposte qui hanno affrontato il problema in modo ammirevole, quindi non ci entrerò.

Parametri di funzione:

Passa per valore: ad es. void func(int param)Non ti interessa in un modo o nell'altro sul sito chiamante. Si può argomentare che ci sono casi d'uso per dichiarare la funzione come void func(int const param)ma che non ha alcun effetto sul chiamante, solo sulla funzione stessa, in quanto qualunque valore viene passato non può essere modificato dalla funzione durante la chiamata.

Passa per riferimento: ad es. void func(int &param)Ora fa la differenza. Come appena dichiarato, funcè consentito cambiare parame qualsiasi sito di chiamata dovrebbe essere pronto a far fronte alle conseguenze. La modifica della dichiarazione in void func(int const &param)modifica del contratto e garanzie che funcora non possono cambiare param, il che significa che ciò che viene passato è ciò che verrà restituito. Come altri hanno notato, questo è molto utile per passare a buon mercato un oggetto di grandi dimensioni che non si desidera modificare. Passare un riferimento è molto più economico del passare un oggetto grande per valore.

Passare da puntatore: ad esempio, void func(int *param)e void func(int const *param)Questi due sono praticamente sinonimo con le loro controparti di riferimento, con l'avvertenza che la funzione chiamata ha ora bisogno di verificare la presenza di nullptrmeno che qualche altro assicura garanzia contrattuale funcche non potrà mai ricevere nullptrin param.

Opinione su questo argomento. Dimostrare la correttezza in un caso come questo è incredibilmente difficile, è fin troppo facile commettere un errore. Quindi non correre rischi e controlla sempre i parametri del puntatore per nullptr. Ti risparmierai dolore e sofferenza e sarà difficile trovare insetti a lungo termine. E per quanto riguarda il costo del controllo, è sporco a buon mercato e nei casi in cui l'analisi statica integrata nel compilatore può gestirlo, l'ottimizzatore lo eliminerà comunque. Attiva Link Time Generation per MSVC o WOPR (credo) per GCC e otterrai un programma ampio, vale a dire anche nelle chiamate di funzione che attraversano un confine del modulo di codice sorgente.

Alla fine di tutto quanto sopra è un caso molto solido per preferire sempre i riferimenti ai puntatori. Sono solo più sicuri a tutto tondo.


3

La const con int su entrambi i lati farà puntatore a int costante :

const int *ptr=&i;

o:

int const *ptr=&i;

constdopo *farà puntatore costante a int :

int *const ptr=&i;

In questo caso tutti questi sono puntatori a numeri interi costanti , ma nessuno di questi sono puntatori costanti:

 const int *ptr1=&i, *ptr2=&j;

In questo caso tutti sono puntatori a numeri interi costanti e ptr2 è puntatore costante a numeri interi costanti . Ma ptr1 non è un puntatore costante:

int const *ptr1=&i, *const ptr2=&j;

3
  • se constè a sinistra di *, si riferisce al valore (non importa se è const into int const)
  • se constè a destra di *, si riferisce al puntatore stesso
  • può essere entrambi allo stesso tempo

Un punto importante: const int *p non significa che il valore a cui ti riferisci è costante !! . Significa che non puoi cambiarlo tramite quel puntatore (nel senso che non puoi assegnare $ * p = ... `). Il valore stesso può essere modificato in altri modi. Per esempio

int x = 5;
const int *p = &x;
x = 6; //legal
printf("%d", *p) // prints 6
*p = 7; //error 

Questo è pensato per essere usato principalmente nelle firme delle funzioni, per garantire che la funzione non possa cambiare accidentalmente gli argomenti passati.


2

Solo per completezza di C seguendo le altre spiegazioni, non sono sicuro per C ++.

  • pp - puntatore a puntatore
  • p - puntatore
  • dati - la cosa indicata, in esempi x
  • grassetto : variabile di sola lettura

pointer

  • p dati - int *p;
  • p dati -int const *p;
  • p dati -int * const p;
  • p dati -int const * const p;

Puntatore al puntatore

  1. dati pp p - int **pp;
  2. dati pp p -int ** const pp;
  3. dati pp p -int * const *pp;
  4. dati pp p -int const **pp;
  5. dati pp p -int * const * const pp;
  6. dati pp p -int const ** const pp;
  7. dati pp p -int const * const *pp;
  8. dati pp p -int const * const * const pp;
// Example 1
int x;
x = 10;
int *p = NULL;
p = &x;
int **pp = NULL;
pp = &p;
printf("%d\n", **pp);

// Example 2
int x;
x = 10;
int *p = NULL;
p = &x;
int ** const pp = &p; // Definition must happen during declaration
printf("%d\n", **pp);

// Example 3
int x;
x = 10;
int * const p = &x; // Definition must happen during declaration
int * const *pp = NULL;
pp = &p;
printf("%d\n", **pp);

// Example 4
int const x = 10; // Definition must happen during declaration
int const * p = NULL;
p = &x;
int const **pp = NULL;
pp = &p;
printf("%d\n", **pp);

// Example 5
int x;
x = 10;
int * const p = &x; // Definition must happen during declaration
int * const * const pp = &p; // Definition must happen during declaration
printf("%d\n", **pp);

// Example 6
int const x = 10; // Definition must happen during declaration
int const *p = NULL;
p = &x;
int const ** const pp = &p; // Definition must happen during declaration
printf("%d\n", **pp);

// Example 7
int const x = 10; // Definition must happen during declaration
int const * const p = &x; // Definition must happen during declaration
int const * const *pp = NULL;
pp = &p;
printf("%d\n", **pp);

// Example 8
int const x = 10; // Definition must happen during declaration
int const * const p = &x; // Definition must happen during declaration
int const * const * const pp = &p; // Definition must happen during declaration
printf("%d\n", **pp);

N-livelli di Dereference

Continua, ma possa l'umanità scomunicarti.

int x = 10;
int *p = &x;
int **pp = &p;
int ***ppp = &pp;
int ****pppp = &ppp;

printf("%d \n", ****pppp);

0
  1. const int*- puntatore intall'oggetto costante .

È possibile modificare il valore del puntatore; non è possibile modificare il valore intdell'oggetto, il puntatore punta a.


  1. const int * const- puntatore costante a intoggetto costante .

Non è possibile modificare il valore del puntatore né il valore intdell'oggetto a cui punta il puntatore.


  1. int const *- puntatore intall'oggetto costante .

Questa affermazione equivale a 1. const int*- È possibile modificare il valore del puntatore ma non è possibile modificare il valore intdell'oggetto, a cui punta il puntatore.


In realtà, esiste una quarta opzione:

  1. int * const- puntatore costante intall'oggetto.

È possibile modificare il valore dell'oggetto a cui punta il puntatore ma non è possibile modificare il valore del puntatore stesso. Il puntatore punta sempre allo stesso intoggetto ma questo valore di questo intoggetto può essere modificato.


Se vuoi determinare un certo tipo di costrutto C o C ++ puoi usare la Regola Spirale / Oraria creata da David Anderson; ma non confondere con la Regola di Anderson fatta da Ross J. Anderson, che è qualcosa di abbastanza distinto.

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.