Conversione implicita da char ** a const char **

Perché il mio compilatore (GCC) non esegue implicitamente il cast da char** a const char** ?

Il seguente codice:

 #include  void print(const char** thing) { std::cout << thing[0] << std::endl; } int main(int argc, char** argv) { print(argv); } 

Dà il seguente errore:

 oi.cpp: In function 'int main(int, char**)': oi.cpp:8:12: error: invalid conversion from 'char**' to 'const char**' [-fpermissive] oi.cpp:3:6: error: initializing argument 1 of 'void print(const char**)' [-fpermissive] 

Una tale conversione ti permetterebbe di inserire un const char* nella tua matrice di char* , che sarebbe insicuro. In print puoi fare:

 thing[0] = "abc"; 

Ora argv[0] a un letterale stringa che non può essere modificato, mentre main aspetta che sia non-const ( char* ). Quindi per la sicurezza del tipo questa conversione non è consentita.

Il link di @Fred Overflow alle FAQ è una risposta completa. Ma (scusa Marshall) non è la spiegazione più chiara. Non so se il mio è più chiaro, ma lo spero.


Il fatto è che, se p è un puntatore char* , allora può essere usato per modificare qualunque cosa stia puntando.

E se potessi ottenere un puntatore pp che punta a p , ma con pp di tipo char const** , potresti usare pp per assegnare a p l’indirizzo di un const char .

E con questo, potresti usare p per modificare il const char . Oppure, penseresti che potresti. Ma quel const char potrebbe anche essere in memoria di sola lettura …

Nel codice:

 char const c = 'a'; char* p = 0; char const** pp = &p; // Not allowed. :-) *pp = &c; // p now points to c. *p = 'b'; // Uh oh. 

Come soluzione pratica al tuo codice che non viene compilato, …

 #include  void print(const char** thing) { std::cout << thing[0] << std::endl; } int main(int argc, char** argv) { print(argv); // Dang, doesn't compile! } 

basta fare …

 #include  void print( char const* const* thing ) { std::cout << thing[0] << std::endl; } int main( int argc, char** argv ) { print( argv ); // OK. :-) } 

Saluti e hth.,

Nota, anche se

 void dosmth(const char** thing); int main(int argc, char** argv) { dosmth(argv); 

è vietato, puoi e devi farlo

 void dosmth(const char* const* thing); int main(int argc, char** argv) { dosmth(argv); 

Che probabilmente è quello che volevi comunque. Il punto qui è che la thing ora si riferisce ad un array const char* che è esso stesso immutabile e che i valori di riferimento char sono essi stessi immutabili. Quindi, per uno scenario ” guardalo ma non cambiarlo “, const char* const* è il tipo da usare.

Nota: ho usato lo standard più comune (ma a mio parere inferiore) di provare a scrivere il modificatore di const più a sinistra ansible. Personalmente, raccomando di scrivere char const* const* invece di const char* const* in quanto è estremamente più conciso in questo modo.

Perché potrebbe permetterci di modificare un valore costante. Leggi qui per capire perché: http://c-faq.com/ansi/constmismatch.html