Quelle est la différence entre
char* name
qui pointe vers un littéral de chaîne constant, et
const char* name
Quelle est la différence entre
char* name
qui pointe vers un littéral de chaîne constant, et
const char* name
Réponses:
char*
est un pointeur mutable vers un caractère / une chaîne mutable .
const char*
est un pointeur mutable vers un caractère / une chaîne immuable . Vous ne pouvez pas modifier le contenu des emplacements vers lesquels ce pointeur pointe. En outre, les compilateurs doivent envoyer des messages d'erreur lorsque vous essayez de le faire. Pour la même raison, la conversion de const char *
en char*
est obsolète.
char* const
est un pointeur immuable (il ne peut pointer vers aucun autre emplacement) mais le contenu de l'emplacement vers lequel il pointe est modifiable .
const char* const
est un pointeur immuable vers un caractère / une chaîne immuable .
char const *
char *
donnera- t-elle pas une erreur de segmentation pendant l'exécution?
const
si je veux que le compilateur donne une erreur si j'ai oublié et changé les données par erreur, non?
char *name
Vous pouvez changer le caractère vers quels name
points, ainsi que le caractère vers lequel il pointe.
const char* name
Vous pouvez changer le caractère vers quels name
points, mais vous ne pouvez pas modifier le caractère vers lequel il pointe.
correction: vous pouvez modifier le pointeur, mais pas le caractère vers lequel name
pointe ( https://msdn.microsoft.com/en-us/library/vstudio/whkd4k6a(v=vs.100).aspx , voir "Exemples" ). Dans ce cas, le const
spécificateur s'applique à char
, pas l'astérisque.
Selon la page MSDN et http://en.cppreference.com/w/cpp/language/declarations , l' const
avant *
fait partie de la séquence de déclinaison, tandis que l' const
après *
fait partie du déclarateur.
Une séquence de spécificateur de déclaration peut être suivie par plusieurs déclarateurs, c'est pourquoi const char * c1, c2
déclare c1
as const char *
et c2
as const char
.
ÉDITER:
D'après les commentaires, votre question semble porter sur la différence entre les deux déclarations lorsque le pointeur pointe vers une chaîne littérale.
Dans ce cas, vous ne devez pas modifier le caractère vers lequel name
pointe, car cela pourrait entraîner un comportement indéfini . Les littéraux de chaîne peuvent être alloués dans des régions de mémoire en lecture seule (implémentation définie) et un programme utilisateur ne doit en aucun cas le modifier. Toute tentative de le faire entraîne un comportement indéfini.
La seule différence dans ce cas (d'utilisation avec des chaînes littérales) est que la deuxième déclaration vous donne un léger avantage. Les compilateurs vous donneront généralement un avertissement au cas où vous tenteriez de modifier la chaîne littérale dans le second cas.
#include <string.h>
int main()
{
char *str1 = "string Literal";
const char *str2 = "string Literal";
char source[] = "Sample string";
strcpy(str1,source); //No warning or error, just Undefined Behavior
strcpy(str2,source); //Compiler issues a warning
return 0;
}
Production:
cc1: les avertissements étant traités comme des erreurs
prog.c: Dans la fonction 'main':
prog.c: 9: erreur: la transmission de l'argument 1 de 'strcpy' élimine les qualificatifs du type de cible du pointeur
Notez que le compilateur avertit pour le deuxième cas mais pas pour le premier.
name
points dans les deux cas, cela pourrait entraîner UB.
char mystring[101] = "My sample string";
const char * constcharp = mystring; // (1)
char const * charconstp = mystring; // (2) the same as (1)
char * const charpconst = mystring; // (3)
constcharp++; // ok
charconstp++; // ok
charpconst++; // compile error
constcharp[3] = '\0'; // compile error
charconstp[3] = '\0'; // compile error
charpconst[3] = '\0'; // ok
// String literals
char * lcharp = "My string literal";
const char * lconstcharp = "My string literal";
lcharp[0] = 'X'; // Segmentation fault (crash) during run-time
lconstcharp[0] = 'X'; // compile error
// *not* a string literal
const char astr[101] = "My mutable string";
astr[0] = 'X'; // compile error
((char*)astr)[0] = 'X'; // ok
char *
valeur donne une erreur de segmentation puisque nous essayons de modifier une chaîne littérale (qui est présente en mémoire morte)
Dans les deux cas, vous ne pouvez pas modifier un littéral de chaîne, que le pointeur vers ce littéral de chaîne soit déclaré char *
ou non const char *
.
Cependant, la différence est que si le pointeur est, const char *
le compilateur doit donner un diagnostic si vous essayez de modifier la valeur pointée, mais si le pointeur est, char *
il ne le fait pas.
extern ... name
et avoir *name = 'X';
. Sur le «bon système d'exploitation», cela pourrait échouer, mais sur les systèmes embarqués, je m'attendrais à ce qu'il fasse quelque chose de spécifique à la plate-forme / au compilateur.
CAS 1:
char *str = "Hello";
str[0] = 'M' //Warning may be issued by compiler, and will cause segmentation fault upon running the programme
Ce qui précède définit str pour pointer vers la valeur littérale "Hello" qui est codée en dur dans l'image binaire du programme, qui est marquée comme lecture seule en mémoire, signifie que toute modification de ce littéral String est illégale et qui entraînerait des erreurs de segmentation.
CAS 2:
const char *str = "Hello";
str[0] = 'M' //Compile time error
CAS 3:
char str[] = "Hello";
str[0] = 'M'; // legal and change the str = "Mello".
Le premier que vous pouvez réellement changer si vous le souhaitez, le second vous ne le pouvez pas. Renseignez-vous sur l' const
exactitude (il existe de bons guides sur la différence). Il y a aussi char const * name
là où vous ne pouvez pas le rejoindre.
La question est de savoir quelle est la différence entre
char *name
qui pointe vers un littéral de chaîne constant, et
const char *cname
Ie donné
char *name = "foo";
et
const char *cname = "foo";
Il n'y a pas beaucoup de différence entre les 2 et les deux peuvent être considérés comme corrects. En raison de la longue tradition du code C, les littéraux de chaîne ont eu un type de char[]
, non const char[]
, et il existe de nombreux codes plus anciens qui acceptent également à la char *
place de const char *
, même s'ils ne modifient pas les arguments.
La principale différence des 2 en général est que *cname
ou cname[n]
va s'évaluer à lvaleurs de type const char
, alors que *name
ou name[n]
va s'évaluer à lvaleurs de type char
, qui sont des lvaleurs modifiables . Un compilateur conforme est requis pour produire un message de diagnostic si la cible de l'affectation n'est pas une lvalue modifiable ; il n'a pas besoin de produire d'avertissement lors de l'affectation à des valeurs de type char
:
name[0] = 'x'; // no diagnostics *needed*
cname[0] = 'x'; // a conforming compiler *must* produce a diagnostics message
Le compilateur n'est pas obligé d'arrêter la compilation dans les deux cas; il suffit qu'il produise un avertissement pour l'affectation à cname[0]
. Le programme résultant n'est pas un programme correct . Le comportement de la construction n'est pas défini . Il peut planter, ou pire encore, il peut ne pas planter et changer la chaîne littérale en mémoire.
En fait, ce char* name
n'est pas un pointeur vers une constante, mais un pointeur vers une variable. Vous parlez peut-être de cette autre question.
Quelle est la différence entre char * const et const char *?