2013-09-05 15 views
11

Mentre questo compila:Assegnazione di puntatori a puntatori con o senza qualificazioni

char* p2c; 
const char* p2cc = p2c; //fine 

perché ss tipo a punta ha tutte le qualificazioni di RHS tipo a punta, questo non lo fa:

char** p2p2c; 
const char** p2p2cc = p2p2c; //fail 

ma questo fa:

const char * const * p2cp2cc = p2p2c; //fine 

Perché esattamente ciò accade?

+1

L'ultimo esempio compilerà solo in C++, ma non in C. – AnT

+0

@AndreyT perché così? – emesx

+0

Questo è solo il modo in cui è in C e C++. Si tratta di due lingue diverse con regole di const-correctness diverse. In C++ 'T **' è convertibile in 'const T * const *'. In C 'T **' è convertibile in 'T * const *', ma non in 'T * const *'. http://stackoverflow.com/a/5249001/187690 – AnT

risposta

7

Questo non funziona:

char** p2p2c; 
const char** p2p2cc = p2p2c; //fail 

Se questo è stato permesso si sarebbe permesso di rompere const correttezza:

const int k = 10; 
int *p; 
int **pp = &p; 
int const **kpp = pp;  // Should this be allowed, if so: 
*kpp = &k;    // fine, kpp promises not to change it 
          // yet this does p = &k; 
          // p made no such promise! this is a hidden const_cast! 
*p = 5; 

Se l'assegnazione è stato permesso, si consentirebbe impostando un puntatore non-const (intermedio) per riferirsi a un valore costante, probabilmente causando un comportamento indefinito in modo non ovvio per vedere. Disabilitando quell'operazione il sistema di tipi è più sicuro.

ma questo fa:

const char * const * p2cp2cc = p2p2c; //fine 

Questo va bene, poiché il puntatore intermedio è fisso, non è possibile ripristinare il puntatore intermedio per fare riferimento a un oggetto const e rompere const correttezza

+0

Perché si può tranquillamente convertire 'char **' in 'char const * const *'? – emesx

+0

@elmes: poiché anche il puntatore intermedio è 'const' significa che non è possibile reimpostarlo sull'oggetto * errato *. –

+0

Sembra abbastanza ragionevole ora, grazie. – emesx

-1

cdecl aiuta davvero in casi come questo.

const char** p2p2cc = declare p2p2cc as pointer to pointer to const char 

e

const char * const * p2cp2cc = declare p2cp2cc as pointer to const pointer to const char 

Come si può vedere, la seconda versione ha l'interno e il puntatore const esterno, il che significa che non può modificare o. La prima versione ha il puntatore INNER const e l'esterno non-const interrompendo così le costanti.

D'altra parte, questo funziona:

char** const p = p2p2c;