Je suis en train de parcourir quelques exemples de programmes pour me familiariser avec C ++ et j'ai rencontré la question suivante. Tout d'abord, voici l'exemple de code:
void print_string(const char * the_string)
{
cout << the_string << endl;
}
int main () {
print_string("What's up?");
}
Dans le code ci-dessus, le paramètre de print_string aurait pu être à la place const char * const the_string
. Qu'est-ce qui serait plus correct pour cela?
Je comprends que la différence est que l'un est un pointeur vers un caractère constant, tandis que l'autre est un pointeur constant vers un caractère constant. Mais pourquoi ces deux méthodes fonctionnent-elles? Quand cela serait-il pertinent?
const char *
est beaucoup mieux parce queconst
c'est du côté complètement opposé.Pointeur mutable vers un caractère mutable
Pointeur mutable vers un caractère constant
Pointeur constant vers un caractère mutable
Pointeur constant vers un caractère constant
la source
const char* p; --> constant pointer to mutable character
etchar *const p; --> mutable pointer to constant character
const char * p
comme: "p est un pointeur vers une constante de caractère" ou un pointeur mutable vers un caractère constant comme James l'affirme correctement. même chose avec le second :).const char * const
signifie que le pointeur ainsi que les données sur lesquelles le pointeur a pointé sont tous les deux const!const char *
signifie que seules les données sur lesquelles le pointeur a pointé sont const. Le pointeur lui-même n'est cependant pas const.Exemple.
la source
(Je sais que c'est vieux mais je voulais quand même partager.)
Je voulais juste développer la réponse de Thomas Matthews. La règle droite-gauche des déclarations de type C dit à peu près: lors de la lecture d'une déclaration de type C, commencez par l'identifiant et allez à droite quand vous le pouvez et à gauche quand vous ne pouvez pas.
Ceci est mieux expliqué avec quelques exemples:
Exemple 1
Commencez par l'identifiant, on ne peut pas aller à droite donc on va à gauche
foo est une constante ...
Continuer à gauche
foo est un pointeur constant vers ...
Continuer à gauche
foo est un pointeur constant vers char ...
Continuer à gauche
foo est un pointeur constant vers la constante char (Complete!)
Exemple 2
Commencez par l'identifiant, on ne peut pas aller à droite donc on va à gauche
foo est une constante ...
Continuer à gauche
foo est un pointeur constant vers ...
Continuer à gauche
foo est un pointeur constant vers char (Complete!)
Exemple 1337
Commencez par l'identifiant, mais maintenant nous pouvons aller bien!
foo est un tableau de 8 ...
Appuyez sur les parenthèses pour ne plus pouvoir aller à droite, allez à gauche
foo est un tableau de 8 pointeurs vers ...
Terminé entre parenthèses, peut maintenant aller à droite
foo est un tableau de 8 pointeurs vers la fonction qui renvoie ...
Rien de plus à droite, va à gauche
foo est un tableau de 8 pointeurs vers une fonction qui renvoie un pointeur vers un ...
Continuer à gauche
foo est un tableau de 8 pointeurs vers des fonctions qui renvoie un pointeur vers une constante ...
Continuer à gauche
foo est un tableau de 8 pointeurs vers des fonctions qui renvoie un pointeur vers un pointeur constant vers un ...
Continuer à gauche
foo est un tableau de 8 pointeurs vers des fonctions qui renvoie un pointeur vers un pointeur constant vers un char ...
Continuer à gauche
foo est un tableau de 8 pointeurs vers des fonctions qui renvoie un pointeur vers un pointeur constant vers une constante char (Complete!)
Explication supplémentaire: http://www.unixwiz.net/techtips/reading-cdecl.html
la source
De nombreuses personnes suggèrent de lire le spécificateur de type de droite à gauche.
Dans les deux formes, le pointeur pointe vers des données constantes ou en lecture seule.
Dans la seconde forme, le pointeur ne peut pas être modifié; le pointeur pointera toujours vers le même endroit.
la source
La différence est que sans le supplément,
const
le programmeur pourrait changer, à l'intérieur de la méthode, l'endroit où le pointeur pointe; par exemple:Ce serait plutôt illégal si la signature était
void print_string(const char * const the_string)
De nombreux programmeurs se sentent trop verbeux (dans la plupart des scénarios) le
const
mot-clé supplémentaire et l'omettent, même s'il serait sémantiquement correct.la source
Dans ce dernier, vous garantissez de ne pas modifier à la fois le pointeur et le caractère dans le premier, vous garantissez seulement que le contenu ne changera pas mais vous pouvez déplacer le pointeur
la source
Il n'y a aucune raison pour que l'un ou l'autre ne fonctionne pas. Il
print_string()
suffit d'imprimer la valeur. Il n'essaye pas de le modifier.C'est une bonne idée de créer une fonction qui ne modifie pas les arguments de marque comme const. L'avantage est que les variables qui ne peuvent pas changer (ou que vous ne voulez pas changer) peuvent être passées à ces fonctions sans erreur.
En ce qui concerne la syntaxe exacte, vous souhaitez indiquer le type d'arguments "sûrs" à transmettre à la fonction.
la source
Je pense que cela varie rarement, car votre fonction n'est pas appelée avec des arguments comme & * the_string ou ** the_string. Le pointeur lui-même est un argument de type valeur, donc même si vous le modifiez, vous n'allez pas changer la copie qui a été utilisée pour appeler votre fonction. La version que vous montrez garantit que la chaîne ne changera pas, et je pense que c'est suffisant dans ce cas.
la source
const char *
signifie que vous ne pouvez pas utiliser le pointeur pour modifier ce qui est pointé. Vous pouvez cependant changer le pointeur pour qu'il pointe vers autre chose.Considérer:
Le paramètre est un pointeur non const vers const char, il peut donc être remplacé par une autre
const char *
valeur (comme une chaîne constante). Si, cependant, nous avons écrit par erreur*text = '\0'
nous obtiendrions une erreur de compilation.On peut soutenir que si vous n'avez pas l'intention de modifier ce vers quoi le paramètre pointe, vous pouvez créer le paramètre
const char * const text
, mais ce n'est pas courant de le faire. Nous autorisons généralement les fonctions à modifier les valeurs passées aux paramètres (car nous transmettons les paramètres par valeur, tout changement n'affecte pas l'appelant).BTW: c'est une bonne pratique à éviter
char const *
car il est souvent mal lu - cela signifie la même chose queconst char *
, mais trop de gens le lisent comme un senschar * const
.la source
const char *
et la signaturechar const *
- la façon dont vous avez formulé votre BTW a vraiment aidé!Presque toutes les autres réponses sont correctes, mais elles manquent un aspect de ceci: lorsque vous utilisez le supplément
const
sur un paramètre dans une déclaration de fonction, le compilateur l'ignorera essentiellement. Pendant un moment, ignorons la complexité de votre exemple étant un pointeur et utilisons simplement unint
.déclare la même fonction que
Ce n'est que dans la définition de la fonction que le supplément est
const
significatif:Cette définition est compatible avec l'une ou l'autre des déclarations ci-dessus. L'appelant ne se soucie pas que ce
x
soitconst
--Que est un détail de mise en œuvre qui ne sont pas pertinentes sur le site d'appel.Si vous avez un
const
pointeur vers desconst
données, les mêmes règles s'appliquent:Peu de programmeurs C ++ se donnent la peine de créer des paramètres
const
, même lorsqu'ils pourraient l'être, que ces paramètres soient ou non des pointeurs.la source
const
à votre paramètre de fonction dans la définition mais pas dans la déclaration.La différence entre les deux est que char * peut pointer vers n'importe quel pointeur arbitraire. Const char * en revanche, pointe vers les constantes définies dans la section DATA de l'exécutable. Et, en tant que tel, vous ne pouvez pas modifier les valeurs de caractères d'une chaîne const char *.
la source
const char*
peut pointer partout où il le souhaite.