La première chose à gauche du "const" est ce qui est constant. Si "const" est la chose la plus à gauche, alors la première chose à droite est ce qui est constant.
Cupcake
4
Comme conseil amical, n'oubliez jamais que cdecl est une chose.
Braden Best
Il y a un autre caractère const * qui est le type de retour d'exception :: what ()
Zhang
Réponses:
363
La différence est qu'il const char *s'agit d'un pointeur vers a const char, tandis que char * constc'est un pointeur constant vers a char.
La première, la valeur pointée ne peut pas être modifiée mais le pointeur peut l'être. La seconde, la valeur pointée peut changer mais pas le pointeur (similaire à une référence).
Il y a aussi
constchar*const
qui est un pointeur constant vers un caractère constant (donc rien à ce sujet ne peut être changé).
Remarque:
Les deux formes suivantes sont équivalentes:
constchar*
et
charconst*
La raison exacte de cela est décrite dans la norme C ++, mais il est important de noter et d'éviter la confusion. Je connais plusieurs normes de codage qui préfèrent:
charconst
plus de
constchar
(avec ou sans pointeur) afin que le placement de l' constélément soit le même qu'avec un pointeur const.
Serait-il intéressant de noter ce qui se passe si plusieurs variables sont spécifiées dans la même déclaration? Je crois const int *foo,*bar;que déclarerait les deux fooet barserait int const *, mais int const *foo, *bardéclarerait fooêtre int const *et barêtre int *. Je pense typedef int * intptr; const intptr foo,bar;que déclarerait les deux variables int * const; Je ne connais aucun moyen d'utiliser une déclaration combinée pour créer deux variables de ce type sans typedef.
supercat
1
@supercat I believe const int *foo,*bar; would declare both foo and bar to be int const *: Oui. but int const *foo, *bar would declare foo to be a int const * and bar to be int *: Non! Ce serait exactement la même chose que dans le cas précédent. (Voir ideone.com/RsaB7n où vous obtenez la même erreur pour foo et bar). I think typedef int * intptr; const intptr foo,bar; would declare both variables to be int * const: Oui. I don't know any way to use a combined declaration to create two variables of that type without a typedef: Eh bien, int *const foo, *const bar;. Syntaxe du déclarant C ...
gx_
@gx_: J'avais donc tort - mon incertitude était la raison pour laquelle j'ai suggéré qu'il pourrait être utile de dire quelles sont les règles. Que ferait int const *foo, *volatile bar-il bar? Faites les deux constet volatile? La séparation nette de Pascal des noms de variables déclarées et de leurs types me manque (un pointeur vers un tableau de pointeurs vers des entiers serait var foo: ^Array[3..4] of ^Integer; `. Ce serait une drôle de parenthèse imbriquée en C, je pense.
supercat
3
@supercat (oh, C-only, désolé pour le lien de code C ++, je suis arrivé ici d'une question C ++) Il s'agit de la syntaxe de déclaration C , avec une partie de type ("pure") suivie d'un déclarateur . Dans " int const *foo, *volatile bar", la partie type est int const(s'arrête avant le *) et les déclarants sont *foo(l'expression *foodénote un int const) et *volatile bar; lire de droite à gauche (bonne règle pour les qualificatifs cv ), fooest un pointeur vers un const int, et barest un pointeur volatil vers un const int (le pointeur lui-même est volatil, le pointé est [accédé comme] const).
gx_
@supercat Et comme pour « un pointeur sur un tableau de pointeurs vers des entiers » (je ne sais pas Pascal, pas sûr de la [3..4]syntaxe, de sorte que nous allons prendre un tableau de 10 éléments): int *(*foo)[10];. Il reflète son utilisation (future) en tant qu'expression: *(*foo)[i](avec iun entier dans la plage, [0, 10)c'est-à-dire [0, 9]) déréférencera d'abord foopour atteindre le tableau, puis accédera à l'élément à l'index i(car postfix []se lie plus étroitement que le préfixe *), puis déréférencer cet élément, enfin donnant un int(voir ideone.com/jgjIjR ). Mais typedefc'est plus facile (voir ideone.com/O3wb7d ).
gx_
102
Pour éviter toute confusion, ajoutez toujours le qualificatif const.
Pourquoi? "Pour éviter la confusion" ne m'explique pas ce qu'est la confusion.
Andrew Weir
14
@Andrew: Je faisais allusion à la cohérence et donc à la lisibilité. J'écris tous les qualificatifs de type pour qu'ils modifient ce qui est à leur gauche, toujours .
diapir
1
En fait, c'est la meilleure réponse sur le sujet que j'ai trouvé dans SO
Trap
8
En tant que norme de code, j'ai rarement rencontré ce style et je ne suis donc pas susceptible de l'adopter. Cependant, en tant qu'outil d'apprentissage, cette réponse a été très utile! (Donc je suppose que ce n'est pas un style plus commun.)
natevw
8
@Alla: pne se rapporte pas au type: (const int *const). Pour le meilleur ou pour le pire (pire si vous me le demandez), le qualificatif const, à la fois en C et C ++, est censé être postfix: cf fonction membre const void foo(int a) const;. La possibilité de déclarer const intest l'exception plutôt que la règle.
diapir
44
const modifie toujours la chose qui la précède (à gauche de celle-ci), SAUF quand c'est la première chose dans une déclaration de type, où elle modifie la chose qui la suit (à sa droite).
Donc, ces deux sont les mêmes:
intconst*i1;constint*i2;
ils définissent des pointeurs vers a const int. Vous pouvez modifier où i1et les i2points, mais vous ne pouvez pas modifier la valeur vers laquelle ils pointent.
Ce:
int*const i3 =(int*)0x12345678;
définit un constpointeur sur un entier et l'initialise pour pointer à l'emplacement de mémoire 12345678. Vous pouvez modifier la intvaleur à l'adresse 12345678, mais vous ne pouvez pas modifier l'adresse qui i3pointe vers.
const * charest un code C invalide et n'a pas de sens. Peut-être vouliez-vous demander la différence entre a const char *et a char const *, ou peut-être la différence entre a const char *et a char * const?
const char*est un pointeur vers un caractère constant char* constest un pointeur constant vers un caractère const char* constest un pointeur constant vers un caractère constant
Règle générale: lisez la définition de droite à gauche!
const int *foo;
Signifie " foopointe ( *) vers un intqui ne peut pas changer ( const)".
Pour le programmeur, cela signifie "Je ne changerai pas la valeur de ce qui foopointe vers".
*foo = 123;ou foo[0] = 123;serait invalide.
foo = &bar; est autorisée.
int *const foo;
Signifie " foone peut pas changer ( const) et pointe ( *) en int".
Pour le programmeur, cela signifie "Je ne changerai pas l' adresse mémoire qui foofait référence à".
*foo = 123;ou foo[0] = 123;est autorisé.
foo = &bar; serait invalide.
const int *const foo;
Signifie " foone peut pas changer ( const) et pointe ( *) sur un intqui ne peut pas changer ( const)".
Pour le programmeur, cela signifie «Je ne changerai pas la valeur de ce qui foopointe vers, ni je ne changerai l' adresse qui foofait référence».
const char * x Ici, X est essentiellement un pointeur de caractère qui pointe vers une valeur constante
char * const x fait référence au pointeur de caractère qui est constant, mais l'emplacement qu'il pointe peut être modifié.
const char * const x est une combinaison de 1 et 2, signifie qu'il s'agit d'un pointeur de caractère constant qui pointe vers une valeur constante.
const * char x provoquera une erreur de compilation. il ne peut pas être déclaré.
char const * x est égal au point 1.
la règle générale est que si const est avec le nom var, le pointeur sera constant mais l'emplacement de pointage peut être modifié , sinon le pointeur pointera vers un emplacement constant et le pointeur peut pointer vers un autre emplacement mais le contenu de l'emplacement de pointage ne peut pas être modifié .
"char * const x fait référence au pointeur de caractère qui est constant, mais l'emplacement qu'il pointe peut être modifié." Faux. La valeur à l'emplacement peut être modifiée et non l'emplacement lui-même.
Aidez
3
Le premier est une erreur de syntaxe. Peut-être que vous vouliez dire la différence entre
constchar* mychar
et
char*const mychar
Dans ce cas, le premier est un pointeur vers des données qui ne peuvent pas changer, et le second est un pointeur qui pointera toujours vers la même adresse.
Beaucoup de réponses fournissent des techniques spécifiques, des règles empiriques, etc. pour comprendre cette instance particulière de déclaration de variable. Mais il existe une technique générique pour comprendre toute déclaration:
Selon la règle horaire / spirale, le apointeur sur le caractère est constant. Ce qui signifie que le caractère est constant mais que le pointeur peut changer. c'est-à a = "other string";- dire est bien, mais a[2] = 'c';ne parviendra pas à compiler
B)
char*const a;
Selon la règle, aest le pointeur const vers un caractère. c'est-à-dire que vous pouvez faire a[2] = 'c';mais vous ne pouvez pas fairea = "other string";
(Ce serait beaucoup mieux si l'essence de la réponse n'était pas cachée derrière un lien, le texte ici ne citant même pas, ou du moins faisant référence, à l'une de ses spécificités, au-delà d'un générique "selon la règle".)
Sz.
@Sz. Avez-vous ici une confusion particulière que je peux clarifier? Il n'y a vraiment pas grand-chose après avoir connu la règle.
PnotNP
1
Je suppose que vous voulez dire const char * et char * const.
Le premier, const char *, est un pointeur sur un caractère constant. Le pointeur lui-même est modifiable.
Le second, char * const est un pointeur constant vers un caractère. Le pointeur ne peut pas changer, le caractère vers lequel il pointe peut.
Et puis il y a const char * const où le pointeur et le caractère ne peuvent pas changer.
Vos deux premiers sont en fait les mêmes et votre troisième est une erreur de compilation :)
workmad3
1
Voici une explication détaillée avec le code
/*const char * p;
char * const p;
const char * const p;*/// these are the three conditions,// const char *p;const char * const p; pointer value cannot be changed// char * const p; pointer address cannot be changed// const char * const p; both cannot be changed.#include<stdio.h>/*int main()
{
const char * p; // value cannot be changed
char z;
//*p = 'c'; // this will not work
p = &z;
printf(" %c\n",*p);
return 0;
}*//*int main()
{
char * const p; // address cannot be changed
char z;
*p = 'c';
//p = &z; // this will not work
printf(" %c\n",*p);
return 0;
}*//*int main()
{
const char * const p; // both address and value cannot be changed
char z;
*p = 'c'; // this will not work
p = &z; // this will not work
printf(" %c\n",*p);
return 0;
}*/
// Some more complex constant variable/pointer declaration.// Observing cases when we get error and warning would help// understanding it better.int main(void){char ca1[10]="aaaa";// char array 1char ca2[10]="bbbb";// char array 2char*pca1= ca1;char*pca2= ca2;charconst*ccs= pca1;char*const csc= pca2;
ccs[1]='m';// Bad - error: assignment of read-only location ‘*(ccs + 1u)’
ccs= csc;// Good
csc[1]='n';// Good
csc= ccs;// Bad - error: assignment of read-only variable ‘csc’charconst**ccss=&ccs;// Goodcharconst**ccss1=&csc;// Bad - warning: initialization from incompatible pointer typechar*const*cscs=&csc;// Goodchar*const*cscs1=&ccs;// Bad - warning: initialization from incompatible pointer typechar**const cssc=&pca1;// Goodchar**const cssc1=&ccs;// Bad - warning: initialization from incompatible pointer typechar**const cssc2=&csc;// Bad - warning: initialization discards ‘const’// qualifier from pointer target type*ccss[1]='x';// Bad - error: assignment of read-only location ‘**(ccss + 8u)’*ccss= ccs;// Good*ccss= csc;// Good
ccss= ccss1;// Good
ccss= cscs;// Bad - warning: assignment from incompatible pointer type*cscs[1]='y';// Good*cscs= ccs;// Bad - error: assignment of read-only location ‘*cscs’*cscs= csc;// Bad - error: assignment of read-only location ‘*cscs’
cscs= cscs1;// Good
cscs= cssc;// Good*cssc[1]='z';// Good*cssc= ccs;// Bad - warning: assignment discards ‘const’// qualifier from pointer target type*cssc= csc;// Good*cssc= pca2;// Good
cssc= ccss;// Bad - error: assignment of read-only variable ‘cssc’
cssc= cscs;// Bad - error: assignment of read-only variable ‘cssc’
cssc= cssc1;// Bad - error: assignment of read-only variable ‘cssc’}
Pointeur constant: Un pointeur constant peut pointer uniquement vers une seule variable du type de données respectif pendant tout le programme. Nous pouvons changer la valeur de la variable pointée par le pointeur. L'initialisation doit être effectuée pendant la période de déclaration elle-même.
Syntaxe:
datatype *const var;
char *const relève de ce cas.
/*program to illustrate the behaviour of constant pointer */#include<stdio.h>int main(){int a=10;int*const ptr=&a;*ptr=100;/* we can change the value of object but we cannot point it to another variable.suppose another variable int b=20; and ptr=&b; gives you error*/
printf("%d",*ptr);return0;}
Pointeur vers une valeur const : un pointeur peut pointer n'importe quel nombre de variables du type respectif, mais nous ne pouvons pas changer la valeur de l'objet pointé par le pointeur à ce moment précis.
Syntaxe:
const datatype *varou datatype const *var
const char* relève de ce cas.
/* program to illustrate the behavior of pointer to a constant*/#include<stdio.h>int main(){int a=10,b=20;intconst*ptr=&a;
printf("%d\n",*ptr);/* *ptr=100 is not possible i.e we cannot change the value of the object pointed by the pointer*/
ptr=&b;
printf("%d",*ptr);/*we can point it to another object*/return0;}
Le constmodificateur est appliqué au terme immédiatement à sa gauche. La seule exception à cela est quand il n'y a rien à sa gauche, alors cela s'applique à ce qui est immédiatement à sa droite.
Ce sont toutes des façons équivalentes de dire "pointeur constant vers une constante char":
Est-il dépendant du compilateur? gcc produit pour "const char const *" et "const const char *" et "char const const *" le même résultat -> le pointeur pourrait pointer vers un autre emplacement.
cosinus0
1
Deux règles
If const is between char and *, it will affect the left one.
If const is not between char and *, it will affect the nearest one.
par exemple
char const *. This is a pointer points to a constant char.
char * const. This is a constant pointer points to a char.
Je voudrais souligner que l'utilisation int const *(ou const int *) ne concerne pas un pointeur pointant vers une const intvariable, mais que cette variable est constpour ce pointeur spécifique.
Par exemple:
int var =10;intconst* _p =&var;
Le code ci-dessus compile parfaitement bien. _ppointe vers une constvariable, varmême si elle-même n'est pas constante.
Réponses:
La différence est qu'il
const char *
s'agit d'un pointeur vers aconst char
, tandis quechar * const
c'est un pointeur constant vers achar
.La première, la valeur pointée ne peut pas être modifiée mais le pointeur peut l'être. La seconde, la valeur pointée peut changer mais pas le pointeur (similaire à une référence).
Il y a aussi
qui est un pointeur constant vers un caractère constant (donc rien à ce sujet ne peut être changé).
Remarque:
Les deux formes suivantes sont équivalentes:
et
La raison exacte de cela est décrite dans la norme C ++, mais il est important de noter et d'éviter la confusion. Je connais plusieurs normes de codage qui préfèrent:
plus de
(avec ou sans pointeur) afin que le placement de l'
const
élément soit le même qu'avec un pointeurconst
.la source
const int *foo,*bar;
que déclarerait les deuxfoo
etbar
seraitint const *
, maisint const *foo, *bar
déclareraitfoo
êtreint const *
etbar
êtreint *
. Je pensetypedef int * intptr; const intptr foo,bar;
que déclarerait les deux variablesint * const
; Je ne connais aucun moyen d'utiliser une déclaration combinée pour créer deux variables de ce type sans typedef.I believe const int *foo,*bar; would declare both foo and bar to be int const *
: Oui.but int const *foo, *bar would declare foo to be a int const * and bar to be int *
: Non! Ce serait exactement la même chose que dans le cas précédent. (Voir ideone.com/RsaB7n où vous obtenez la même erreur pour foo et bar).I think typedef int * intptr; const intptr foo,bar; would declare both variables to be int * const
: Oui.I don't know any way to use a combined declaration to create two variables of that type without a typedef
: Eh bien,int *const foo, *const bar;
. Syntaxe du déclarant C ...int const *foo, *volatile bar
-ilbar
? Faites les deuxconst
etvolatile
? La séparation nette de Pascal des noms de variables déclarées et de leurs types me manque (un pointeur vers un tableau de pointeurs vers des entiers seraitvar foo: ^Array[3..4] of ^Integer
; `. Ce serait une drôle de parenthèse imbriquée en C, je pense.int const *foo, *volatile bar
", la partie type estint const
(s'arrête avant le*
) et les déclarants sont*foo
(l'expression*foo
dénote unint const
) et*volatile bar
; lire de droite à gauche (bonne règle pour les qualificatifs cv ),foo
est un pointeur vers un const int, etbar
est un pointeur volatil vers un const int (le pointeur lui-même est volatil, le pointé est [accédé comme] const).[3..4]
syntaxe, de sorte que nous allons prendre un tableau de 10 éléments):int *(*foo)[10];
. Il reflète son utilisation (future) en tant qu'expression:*(*foo)[i]
(aveci
un entier dans la plage,[0, 10)
c'est-à-dire[0, 9]
) déréférencera d'abordfoo
pour atteindre le tableau, puis accédera à l'élément à l'indexi
(car postfix[]
se lie plus étroitement que le préfixe*
), puis déréférencer cet élément, enfin donnant unint
(voir ideone.com/jgjIjR ). Maistypedef
c'est plus facile (voir ideone.com/O3wb7d ).Pour éviter toute confusion, ajoutez toujours le qualificatif const.
la source
p
ne se rapporte pas au type:(const int *const)
. Pour le meilleur ou pour le pire (pire si vous me le demandez), le qualificatif const, à la fois en C et C ++, est censé être postfix: cf fonction membre constvoid foo(int a) const;
. La possibilité de déclarerconst int
est l'exception plutôt que la règle.const
modifie toujours la chose qui la précède (à gauche de celle-ci), SAUF quand c'est la première chose dans une déclaration de type, où elle modifie la chose qui la suit (à sa droite).Donc, ces deux sont les mêmes:
ils définissent des pointeurs vers a
const int
. Vous pouvez modifier oùi1
et lesi2
points, mais vous ne pouvez pas modifier la valeur vers laquelle ils pointent.Ce:
définit un
const
pointeur sur un entier et l'initialise pour pointer à l'emplacement de mémoire 12345678. Vous pouvez modifier laint
valeur à l'adresse 12345678, mais vous ne pouvez pas modifier l'adresse quii3
pointe vers.la source
const * char
est un code C invalide et n'a pas de sens. Peut-être vouliez-vous demander la différence entre aconst char *
et achar const *
, ou peut-être la différence entre aconst char *
et achar * const
?Voir également:
la source
const char*
est un pointeur vers un caractère constantchar* const
est un pointeur constant vers un caractèreconst char* const
est un pointeur constant vers un caractère constantla source
Règle générale: lisez la définition de droite à gauche!
const int *foo;
Signifie "
foo
pointe (*
) vers unint
qui ne peut pas changer (const
)".Pour le programmeur, cela signifie "Je ne changerai pas la valeur de ce qui
foo
pointe vers".*foo = 123;
oufoo[0] = 123;
serait invalide.foo = &bar;
est autorisée.int *const foo;
Signifie "
foo
ne peut pas changer (const
) et pointe (*
) enint
".Pour le programmeur, cela signifie "Je ne changerai pas l' adresse mémoire qui
foo
fait référence à".*foo = 123;
oufoo[0] = 123;
est autorisé.foo = &bar;
serait invalide.const int *const foo;
Signifie "
foo
ne peut pas changer (const
) et pointe (*
) sur unint
qui ne peut pas changer (const
)".Pour le programmeur, cela signifie «Je ne changerai pas la valeur de ce qui
foo
pointe vers, ni je ne changerai l' adresse quifoo
fait référence».*foo = 123;
oufoo[0] = 123;
serait invalide.foo = &bar;
serait invalide.la source
const char * x Ici, X est essentiellement un pointeur de caractère qui pointe vers une valeur constante
char * const x fait référence au pointeur de caractère qui est constant, mais l'emplacement qu'il pointe peut être modifié.
const char * const x est une combinaison de 1 et 2, signifie qu'il s'agit d'un pointeur de caractère constant qui pointe vers une valeur constante.
const * char x provoquera une erreur de compilation. il ne peut pas être déclaré.
char const * x est égal au point 1.
la règle générale est que si const est avec le nom var, le pointeur sera constant mais l'emplacement de pointage peut être modifié , sinon le pointeur pointera vers un emplacement constant et le pointeur peut pointer vers un autre emplacement mais le contenu de l'emplacement de pointage ne peut pas être modifié .
la source
Le premier est une erreur de syntaxe. Peut-être que vous vouliez dire la différence entre
et
Dans ce cas, le premier est un pointeur vers des données qui ne peuvent pas changer, et le second est un pointeur qui pointera toujours vers la même adresse.
la source
Une autre règle empirique consiste à vérifier où est const :
la source
Beaucoup de réponses fournissent des techniques spécifiques, des règles empiriques, etc. pour comprendre cette instance particulière de déclaration de variable. Mais il existe une technique générique pour comprendre toute déclaration:
UNE)
Selon la règle horaire / spirale, le
a
pointeur sur le caractère est constant. Ce qui signifie que le caractère est constant mais que le pointeur peut changer. c'est-àa = "other string";
- dire est bien, maisa[2] = 'c';
ne parviendra pas à compilerB)
Selon la règle,
a
est le pointeur const vers un caractère. c'est-à-dire que vous pouvez fairea[2] = 'c';
mais vous ne pouvez pas fairea = "other string";
la source
Je suppose que vous voulez dire const char * et char * const.
Le premier, const char *, est un pointeur sur un caractère constant. Le pointeur lui-même est modifiable.
Le second, char * const est un pointeur constant vers un caractère. Le pointeur ne peut pas changer, le caractère vers lequel il pointe peut.
Et puis il y a const char * const où le pointeur et le caractère ne peuvent pas changer.
la source
Voici une explication détaillée avec le code
la source
la source
Syntaxe:
char *const
relève de ce cas.Syntaxe:
const datatype *var
oudatatype const *var
const char*
relève de ce cas.la source
char * const et const char *?
const char * p;
// la valeur ne peut pas être modifiéechar * const p;
// l'adresse ne peut pas être modifiéeconst char * const p;
// les deux ne peuvent pas être modifiés.la source
Le
const
modificateur est appliqué au terme immédiatement à sa gauche. La seule exception à cela est quand il n'y a rien à sa gauche, alors cela s'applique à ce qui est immédiatement à sa droite.Ce sont toutes des façons équivalentes de dire "pointeur constant vers une constante
char
":const char * const
const char const *
char const * const
char const const *
la source
Deux règles
If const is between char and *, it will affect the left one.
If const is not between char and *, it will affect the nearest one.
par exemple
char const *. This is a pointer points to a constant char.
char * const. This is a constant pointer points to a char.
la source
Je voudrais souligner que l'utilisation
int const *
(ouconst int *
) ne concerne pas un pointeur pointant vers uneconst int
variable, mais que cette variable estconst
pour ce pointeur spécifique.Par exemple:
Le code ci-dessus compile parfaitement bien.
_p
pointe vers uneconst
variable,var
même si elle-même n'est pas constante.la source
Je me souviens d'un livre tchèque sur C: lisez la déclaration que vous commencez avec la variable et allez à gauche. Donc pour
vous pouvez lire comme: "
a
est une variable de type pointeur constant verschar
",vous pouvez lire comme: "
a
est un pointeur vers une variable constante de type char. J'espère que cela aide.Prime:
Vous lirez tel
a
quel un pointeur constant vers une variable constante de type char.la source