2013-09-05 13 views
11

Chociaż kompiluje:Przypisywanie wskaźniki do wskaźników z lub bez kwalifikatorów

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

ponieważ lewa spiczasty typ ma wszystkie kwalifikacyjne z rhs spiczastym typu, to nie:

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

ale to robi:

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

Dlaczego tak się dzieje?

+1

Ostatnim przykładem będzie skompilować tylko w C++, ale nie w C. – AnT

+0

@AndreyT dlaczego tak? – emesx

+0

Tak właśnie jest w C i C++. Są to dwa różne języki z różnymi regułami poprawności stałych. W C++ 'T **' można przekształcić na 'const T * const *'. W C 'T **' można zamienić na 'T * const *', ale nie na 'T * const *'. http://stackoverflow.com/a/5249001/187690 – AnT

Odpowiedz

7

To nie działa:

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

Jeśli pozwolono by mieć prawo do zerwania const-poprawności:

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; 

Jeśli zadanie było dozwolone, byś umożliwić ustawianie wskaźnika niestałego (pośredniego) w celu odniesienia do wartości stałej, co może spowodować niezdefiniowane zachowanie w sposób nieoczywisty, aby zobaczyć. Przez uniemożliwienie tej operacji system typów jest bezpieczniejszy.

ale to robi:

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

Jest to dobre rozwiązanie, ponieważ pośredni wskaźnik jest ustalony, nie jest możliwe, aby zresetować pośredni wskaźnik odnosi się do const obiektu i złamać const-poprawności

+0

Dlaczego można bezpiecznie przekonwertować 'char **' na 'char const * const *'? – emesx

+0

@elmes: ponieważ wskaźnik pośredni będący również "const" oznacza, że ​​nie można go zresetować do * niewłaściwego * obiektu. –

+0

Teraz wydaje się całkiem rozsądna, dziękuję. – emesx

-1

cdecl naprawdę pomaga w takich przypadkach.

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

i

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

Jak widać, druga wersja ma wewnętrzną i zewnętrzną wskaźnik const, co oznacza, że ​​nie można modyfikować albo. Pierwsza wersja ma wskaźnik WEWNĘTRZ const, a zewnętrzny niestanowiący const, łamiąc w ten sposób constnes.

Z drugiej strony, to działa:

char** const p = p2p2c; 
Powiązane problemy