web-dev-qa-db-fra.com

Différence entre char * et const char *?

Quelle est la différence entre 

char* name

qui pointe vers un littéral de chaîne constant, et 

const char* name
143
Iceman

char* est un mutable pointeur sur un mutable caractère/chaîne.

const char* est un mutable pointeur sur un immuable caractère/chaîne. Vous ne pouvez pas modifier le contenu des emplacements sur lesquels pointe le pointeur. En outre, les compilateurs sont tenus de donner des messages d'erreur lorsque vous essayez de le faire. Pour la même raison, la conversion de const char * à char* est obsolète.

char* const est un immuable pointeur (il ne peut pointer vers aucun autre emplacement) mais le contenu de l’emplacement sur lequel il pointe est mutable .

const char* const est un immuable pointeur sur un immuable caractère/chaîne.

325
ankit.karwasra
char *name

Vous pouvez changer le caractère sur lequel name pointe, ainsi que le caractère sur lequel il pointe.

const char* name

Vous pouvez modifier le caractère sur lequel name pointe, mais vous ne pouvez pas modifier le caractère sur lequel il pointe.
correction: Vous pouvez modifier le pointeur, mais pas le caractère vers lequel name pointe vers ( https://msdn.Microsoft .com/fr-us/library/vstudio/whkd4k6a (v = vs.100) .aspx , voir "Exemples"). Dans ce cas, le spécificateur const s'applique à char, pas à l'astérisque.

Selon la page MSDN et http://en.cppreference.com/w/cpp/language/declarations , le const précédant le * fait partie de la séquence decl-specifier, tandis que le const après * fait partie de le déclarant. 
Une séquence de spécificateur de déclaration peut être suivie de plusieurs déclarants, raison pour laquelle const char * c1, c2 déclare c1 en tant que const char * et c2 en tant que const char.

MODIFIER:

D'après les commentaires, votre question semble porter sur la différence entre les deux déclarations lorsque le pointeur pointe sur un littéral de chaîne. 

Dans ce cas, vous ne devriez pas modifier le caractère pointé par name car il pourrait en résulter Undefined Behavior . Des littéraux de chaîne peuvent être alloués dans des régions de mémoire en lecture seule (définies par l'implémentation) et programme utilisateur ne doit en aucun cas le modifier. Toute tentative en ce sens entraîne un comportement indéfini. 

Ainsi, la seule différence dans ce cas (d'utilisation avec les littéraux de chaîne) est que la deuxième déclaration vous donne un léger avantage. Les compilateurs vous préviendront généralement si vous essayez de modifier le littéral chaîne dans le second cas.

Exemple en ligne:

#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;
}

Sortie: 

cc1: les avertissements sont traités comme des erreurs
prog.c: en fonction 'main':
prog.c: 9: erreur: passer l'argument 1 de 'strcpy' rejette les qualificateurs du type de cible pointeur 

Notez que le compilateur met en garde pour le second cas, mais pas pour le premier.

41
Alok Save
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
15
Afriza N. Arief

Dans les deux cas, vous ne pouvez modifier un littéral de chaîne, que le pointeur sur ce littéral de chaîne soit déclaré ou non en tant que char * ou const char *.

Cependant, la différence est que si le pointeur est const char *, le compilateur doit alors établir un diagnostic si vous essayez de modifier la valeur pointée, mais si le pointeur est char *, ce n'est pas le cas.

9
caf

Le premier que vous pouvez réellement changer si vous le souhaitez, le second, vous ne le pouvez pas. Renseignez-vous sur l'exactitude const (il y a quelques guides de Nice sur la différence). Il y a aussi char const * name où vous ne pouvez pas le renommer.

2
chikuba

CAS 1:

char *str = "Hello";
str[0] = 'M'  //No warning or error, just Undefined Behavior

Les commandes ci-dessus définissent str pour pointer sur la valeur littérale "Hello" qui est codée en dur dans l'image binaire du programme, qui est marquée en lecture seule dans la mémoire, signifie que toute modification de ce littéral String est illégale et risque de générer des erreurs de segmentation.

CAS 2:

const char *str = "Hello";
str[0] = 'M'  //Compiler issues a warning

CAS 3:

char str[] = "Hello";
str[0] = 'M'; // legal and change the str = "Mello".
2
Mohit

En fait, char* name n'est pas un pointeur sur une constante, mais un pointeur sur une variable. Vous parlez peut-être de cette autre question.

Quelle est la difference entre char * const et const char *?

1
Jeff Wolski

La question est quelle est la différence entre

char *name

qui pointe vers un littéral de chaîne constant, et

const char *cname

C'est à dire. donné 

char *name = "foo";

et

const char *cname = "foo";

Il n'y a pas beaucoup de différence entre le 2 et les deux peuvent être considérés comme corrects. En raison du long héritage du code C, les littéraux de chaîne ont eu le type char[], et non pas const char[], et de nombreux codes plus anciens acceptent également char * au lieu de const char *, même lorsqu'ils ne modifient pas les arguments. 

La différence principale des 2 en général est que *cname ou cname[n] sera évalué à des valeurs de type const char, alors que *name ou à name[n] sera évalué à des valeurs de type char, qui sont lvalues ​​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'est pas nécessaire de produire d'avertissement sur 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 warning pour l'affectation à cname[0]. Le programme résultant n'est pas un programme correct. Le comportement de la construction est undefined. Il peut tomber en panne ou, pire encore, ne pas tomber en panne et modifier le littéral chaîne en mémoire.

1
Antti Haapala

Juste pour donner un exemple supplémentaire: 

    std::cout << typeid(2.3).name() << '\n'; // -----> prints "double" simply because
    //2.3 is a double
    //But the "double" returned by typeid(2.3).name() is indeed a 
    //const char * which consists of 'd','o','u','b','l','e'and'\0'.
    //Here's a simple proof to this:
    std::cout << typeid(typeid(2.3).name()).name() << '\n'; //prints: "const char *"
    const char* charptr
    charptr = typeid(2.3).name();
    std::cout << charptr[3]; // --------->  prints: "b"

(J'utilise la bibliothèque typeinfo: http://www.cplusplus.com/reference/typeinfo/type_info/name )

    //Now let's do something more interesting:
    char* charptr2="hubble";
    strcpy(charptr, charptr2);  // --------> Oops! Sorry, this is not valid!

Vous pouvez l'exécuter et voir les choses mieux pour vous-même.

0
M-J