Pourquoi mon compilateur (GCC) ne convertit-il pas implicitement de char**
en const char**
?
Le code suivant:
#include void print(const char** thing) { std::cout << thing[0] << std::endl; } int main(int argc, char** argv) { print(argv); }
Donne l’erreur suivante:
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]
Une telle conversion vous permettrait de mettre un const char*
dans votre tableau de char*
, ce qui serait dangereux. En print
vous pouvez faire:
thing[0] = "abc";
Maintenant, argv[0]
pointe vers un littéral de chaîne qui ne peut pas être modifié, alors que main
s’attend à ce qu’il soit non const ( char*
). Donc, pour la sécurité de type, cette conversion n’est pas autorisée.
Le lien de @Fred Overflow vers la FAQ est une réponse complète. Mais (désolé Marshall), l’explication n’est pas très claire. Je ne sais pas si le mien est plus clair, mais je l’espère.
Le fait est que si p
est un pointeur char*
, il peut alors être utilisé pour modifier son contenu.
Et si vous pouviez obtenir un pointeur pp
qui pointe vers p
, mais avec pp
de type char const**
, vous pouvez utiliser pp
pour affecter à p
l’adresse d’un caractère const char
.
Et avec cela, vous pourriez alors utiliser p
pour modifier le caractère const char
. Ou, vous pourriez penser que vous pourriez. Mais ce caractère const char
pourrait même être dans la mémoire en lecture seule…
Dans du code:
char const c = 'a'; char* p = 0; char const** pp = &p; // Not allowed. :-) *pp = &c; // p now points to c. *p = 'b'; // Uh oh.
En tant que solution pratique à votre code qui ne comstack pas,…
#include void print(const char** thing) { std::cout << thing[0] << std::endl; } int main(int argc, char** argv) { print(argv); // Dang, doesn't compile! }
fais juste…
#include void print( char const* const* thing ) { std::cout << thing[0] << std::endl; } int main( int argc, char** argv ) { print( argv ); // OK. :-) }
Vive & hth.,
Notez que même si
void dosmth(const char** thing); int main(int argc, char** argv) { dosmth(argv);
est interdit, vous pouvez et devriez faire
void dosmth(const char* const* thing); int main(int argc, char** argv) { dosmth(argv);
Ce qui est probablement ce que tu voulais de toute façon. Le point ici est que cette thing
se réfère maintenant à un tableau const char*
qui est lui-même immuable et dont les valeurs référencées char
sont elles-mêmes immuables. Donc, pour un scénario ” regardez, mais ne le changez pas “, const char* const*
est le type à utiliser.
Remarque: j’ai utilisé la norme la plus courante (mais inférieure selon moi) consistant à essayer d’écrire le modificateur de const
plus à gauche possible. Personnellement, je recommande d’écrire char const* const*
au lieu de const char* const*
car const char* const*
car c’est extrêmement concis.
Parce que cela pourrait nous permettre de modifier une valeur constante. Lisez ici pour comprendre pourquoi: http://c-faq.com/ansi/constmismatch.html