Expressions de pointeur: * ptr ++, * ++ ptr et ++ * ptr

128

Récemment, je suis tombé sur ce problème que je suis incapable de comprendre par moi-même.

Que signifient VRAIMENT ces trois expressions ?

*ptr++
*++ptr
++*ptr

J'ai essayé Ritchie. Mais malheureusement, il n'a pas pu suivre ce qu'il a dit sur ces 3 opérations.

Je sais qu'ils sont tous effectués pour incrémenter le pointeur / la valeur pointée. Je peux également deviner qu'il y a peut-être beaucoup de choses sur la préséance et l'ordre d'évaluation. Comme on incrémente d'abord le pointeur puis récupère le contenu de ce pointeur, on récupère simplement le contenu et ensuite incrémente le pointeur, etc. Comme vous pouvez le voir, je n'ai pas une compréhension claire de leurs opérations réelles , ce que je voudrais effacer dès que possible. Mais je suis vraiment perdu quand j'ai la chance de les appliquer dans des programmes. Par exemple:

int main()
{
    const char *p = "Hello";
    while(*p++)
         printf("%c",*p);
    return 0;
}

me donne cette sortie:

ello

Mais je m'attendais à ce qu'il s'imprime Hello. Une dernière demande - Veuillez me donner des exemples du fonctionnement de chaque expression dans un extrait de code donné. Comme la plupart du temps, seul un simple paragraphe de théorie passe au-dessus de ma tête.

attribué
la source
6
Vous avez manqué le quatrième: (*ptr)++(les parenthèses sont nécessaires pour *ptr++
lever l'ambiguïté
15
Parce que vous avez incrémenté le pointeur avant de l'imprimer. Vous vouliez while (* p) et printf ("% c", * p ++);
dcaswell
Excellentes questions pour l'entrevue. Utilisation pratique limitée. J'aimerais que C n'ait pas ces pointeurs :)
Himanshu
5
@Himanshu Si cela fait cuire la nouille de votre interlocuteur, essayez ceci: Ayez un pointeur global ,, char* ppointant vers une chaîne terminée valide de caractères uniques. Ensuite, ayez une fonction fn(char ch)qui imprime à la fois le chparamètre et le caractère actuel pointés par p. Invoquez maintenant fn(*p++);Q: fnimprime- t -il deux fois le même caractère ? Vous seriez étonné de voir combien de professeurs se trompent sur cette question.
WhozCraig
1
puisque p pointe vers une chaîne littérale, vous devriez écrireconst char* p = "Hello";
hetepeperfan

Réponses:

275

Voici une explication détaillée qui, je l'espère, vous sera utile. Commençons par votre programme, car c'est le plus simple à expliquer.

int main()
{
    const char *p = "Hello";
    while(*p++)
        printf("%c",*p);
    return 0;
}

La première déclaration:

const char* p = "Hello";

déclare pcomme un pointeur vers char. Lorsque nous disons "pointeur vers un char", qu'est-ce que cela signifie? Cela signifie que la valeur de pest l'adresse de a char; pnous indique où dans la mémoire il y a un espace réservé pour contenir un fichier char.

L'instruction s'initialise également ppour pointer sur le premier caractère de la chaîne littérale "Hello". Pour les besoins de cet exercice, il est important de comprendre pqu'il ne pointe pas vers la chaîne entière, mais uniquement vers le premier caractère 'H',. Après tout, pest un pointeur vers un char, pas vers la chaîne entière. La valeur de pest l'adresse du 'H'in "Hello".

Ensuite, vous configurez une boucle:

while (*p++)

Que signifie la condition de boucle *p++? Trois choses sont à l'œuvre ici qui rendent cela déroutant (du moins jusqu'à ce que la familiarité s'installe):

  1. La priorité des deux opérateurs, postfix ++et indirection*
  2. La valeur d'une expression d'incrémentation de suffixe
  3. L'effet secondaire d'une expression d'incrément postfix

1. Préséance . Un rapide coup d'œil à la table de priorité des opérateurs vous indiquera que l'incrément de suffixe a une priorité plus élevée (16) que la déréférence / indirection (15). Cela signifie que l'expression complexe *p++va être regroupés comme suit: *(p++). C'est-à-dire que la *pièce sera appliquée à la valeur de la p++pièce. Alors commençons par le p++rôle.

2. Valeur de l'expression Postfix . La valeur de p++est la valeur d' p avant l'incrément . Si tu as:

int i = 7;
printf ("%d\n", i++);
printf ("%d\n", i);

la sortie sera:

7
8

car i++évalue iavant l'incrément. De même p++va évaluer la valeur actuelle de p. Comme nous le savons, la valeur actuelle de pest l'adresse de 'H'.

Alors maintenant, la p++partie de *p++a été évaluée; c'est la valeur actuelle de p. Ensuite, la *partie se produit. *(current value of p)signifie: accéder à la valeur à l'adresse détenue par p. Nous savons que la valeur à cette adresse est 'H'. Ainsi, l'expression est *p++évaluée à 'H'.

Maintenant, attendez une minute, dites-vous. Si *p++évalue à 'H', pourquoi cela ne 'H's'imprime pas dans le code ci-dessus? C'est là qu'interviennent les effets secondaires .

3. Effets secondaires d'expression de Postfix . Le suffixe ++a la valeur de l'opérande actuel, mais il a pour effet secondaire d'incrémenter cet opérande. Hein? Jetez à nouveau un coup d'œil à ce intcode:

int i = 7;
printf ("%d\n", i++);
printf ("%d\n", i);

Comme indiqué précédemment, la sortie sera:

7
8

Quand i++est évalué dans le premier printf(), il évalue à 7. Mais le standard C garantit qu'à un moment donné avant que le second ne printf()commence à s'exécuter, l' effet secondaire de l' ++opérateur aura eu lieu. C'est-à-dire, avant que le second ne printf()se produise, iaura été incrémenté du fait de l' ++opérateur dans le premier printf(). C'est d'ailleurs l'une des rares garanties que la norme donne sur le moment des effets secondaires.

Dans votre code, lorsque l'expression *p++est évaluée, elle est évaluée à 'H'. Mais au moment où vous arrivez à ceci:

printf ("%c", *p)

cet effet secondaire embêtant s'est produit. pa été incrémenté. Whoa! Il ne pointe plus vers 'H', mais vers un personnage passé 'H': vers le 'e', en d'autres termes. Cela explique votre sortie cockneyfied:

ello

D'où le refrain de suggestions utiles (et précises) dans les autres réponses: pour imprimer la prononciation reçue "Hello"et non son homologue cockney, vous avez besoin de quelque chose comme

while (*p)
    printf ("%c", *p++);

Tellement pour ça. Qu'en est-il du reste? Vous demandez la signification de ces derniers:

*ptr++
*++ptr
++*ptr

Nous venons de parler de la première, alors regardons la seconde: *++ptr.

Nous avons vu dans notre explication précédente que l'incrément de suffixe p++a une certaine priorité , une valeur et un effet secondaire . L'incrément de préfixe ++pa le même effet secondaire que son homologue postfixe: il incrémente son opérande de 1. Cependant, il a une priorité et une valeur différentes .

L'incrément de préfixe a une priorité inférieure à celle du suffixe; il a la priorité 15. En d'autres termes, il a la même priorité que l'opérateur de déréférence / indirection *. Dans une expression comme

*++ptr

ce qui compte, ce n'est pas la priorité: les deux opérateurs sont identiques en priorité. L' associativité entre donc en jeu. L'incrément de préfixe et l'opérateur d'indirection ont une associativité droite-gauche. En raison de cette associativité, l'opérande ptrva être groupé avec l'opérateur ++le plus à droite avant l'opérateur le plus à gauche *,. En d'autres termes, l'expression va être groupée *(++ptr). Donc, comme pour *ptr++mais pour une raison différente, ici aussi la *pièce va être appliquée à la valeur de la ++ptrpièce.

Alors, quelle est cette valeur? La valeur de l'expression d'incrément de préfixe est la valeur de l'opérande après l'incrément . Cela en fait une bête très différente de l'opérateur d'incrémentation postfix. Disons que vous avez:

int i = 7;
printf ("%d\n", ++i);
printf ("%d\n", i);

La sortie sera:

8
8

... différent de ce que nous avons vu avec l'opérateur postfix. De même, si vous avez:

const char* p = "Hello";
printf ("%c ", *p);    // note space in format string
printf ("%c ", *++p);  // value of ++p is p after the increment
printf ("%c ", *p++);  // value of p++ is p before the increment
printf ("%c ", *p);    // value of p has been incremented as a side effect of p++

la sortie sera:

H e e l                // good dog

Voyez-vous pourquoi?

Maintenant , nous arrivons à la troisième expression que vous avez parlé, ++*ptr. C'est le plus délicat du lot, en fait. Les deux opérateurs ont la même priorité et la même associativité droite-gauche. Cela signifie que l'expression sera groupée ++(*ptr). La ++pièce sera appliquée à la valeur de la *ptrpièce.

Donc, si nous avons:

char q[] = "Hello";
char* p = q;
printf ("%c", ++*p);

le résultat étonnamment égoïste va être:

I

Quoi?! Ok, donc la *ppartie va être évaluée 'H'. Ensuite, le ++entre en jeu, à quel point, il va être appliqué au 'H'pointeur, pas du tout! Que se passe-t-il lorsque vous ajoutez 1 à 'H'? Vous obtenez 1 plus la valeur ASCII de 'H'72; vous obtenez 73. certifiez que comme char, et vous obtenez la charavec la valeur ASCII de 73: 'I'.

Cela prend en compte les trois expressions que vous avez posées dans votre question. En voici une autre, mentionnée dans le premier commentaire de votre question:

(*ptr)++ 

Celui-là est intéressant aussi. Si tu as:

char q[] = "Hello";
char* p = q;
printf ("%c", (*p)++);
printf ("%c\n", *p);

cela vous donnera cette sortie enthousiaste:

HI

Que se passe-t-il? Encore une fois, c'est une question de priorité , de valeur d'expression et d' effets secondaires . En raison des parenthèses, la *ppièce est traitée comme une expression principale. Les expressions primaires l'emportent sur tout le reste; ils sont évalués en premier. Et *p, comme vous le savez, évalue à 'H'. Le reste de l'expression, la ++partie, est appliqué à cette valeur. Donc, dans ce cas, (*p)++devient 'H'++.

Quelle est la valeur de 'H'++? Si vous avez dit 'I', vous avez oublié (déjà!) Notre discussion sur la valeur par rapport aux effets secondaires avec incrément de suffixe. N'oubliez pas, 'H'++évalue à la valeur actuelle de 'H' . Donc, ce premier printf()va être imprimé 'H'. Ensuite, comme effet secondaire , cela 'H'va être incrémenté 'I'. Le second l' printf()imprime 'I'. Et vous avez votre joyeux salut.

D'accord, mais dans ces deux derniers cas, pourquoi ai-je besoin

char q[] = "Hello";
char* p = q;

Pourquoi ne puis-je pas avoir quelque chose comme

/*const*/ char* p = "Hello";
printf ("%c", ++*p);   // attempting to change string literal!

Parce que "Hello"est une chaîne littérale. Si vous essayez ++*p, vous essayez de changer le 'H'dans la chaîne en 'I', créant ainsi toute la chaîne "Iello". En C, les littéraux de chaîne sont en lecture seule; tenter de les modifier appelle un comportement indéfini. "Iello"n'est pas défini en anglais également, mais ce n'est qu'une coïncidence.

Inversement, vous ne pouvez pas avoir

char p[] = "Hello";
printf ("%c", *++p);  // attempting to modify value of array identifier!

Pourquoi pas? Parce que dans ce cas, pest un tableau. Un tableau n'est pas une valeur l modifiable; vous ne pouvez pas changer les ppoints par pré- ou post-incrémentation ou décrémentation, car le nom du tableau fonctionne comme s'il s'agissait d'un pointeur constant. (Ce n'est pas ce que c'est réellement; c'est juste un moyen pratique de le regarder.)

Pour résumer, voici les trois choses que vous avez posées:

*ptr++   // effectively dereferences the pointer, then increments the pointer
*++ptr   // effectively increments the pointer, then dereferences the pointer
++*ptr   // effectively dereferences the pointer, then increments dereferenced value

Et en voici un quatrième, tout aussi amusant que les trois autres:

(*ptr)++ // effectively forces a dereference, then increments dereferenced value

Le premier et le second planteront s'il ptrs'agit en fait d'un identifiant de tableau. Les troisième et quatrième planteront si elles ptrpointent vers une chaîne littérale.

Voilà. J'espère que tout est en cristal maintenant. Vous avez été un public formidable et je serai ici toute la semaine.

verbeux
la source
22
Avant de venir sur ce forum, j'ai recherché 3 livres "C" que je possède. J'ai également essayé quelques didacticiels en ligne notables. Mais aucun d'entre eux ne se rapproche de votre explication (en particulier la façon dont vous avez tout rassemblé). Vous avez non seulement répondu à la question que j'ai posée, mais vous avez également discuté de beaucoup plus de choses au niveau de la base. En fait, vous m'avez appris beaucoup de choses de base aujourd'hui, ce qui me manquait auparavant. Je n'ai pas pu m'empêcher de basculer ma réponse acceptée. :) Merci encore.
attribué
26
+1 Je pense que c'est la meilleure réponse longue que j'ai lue sur SO. Je pense que tout le monde pourrait apprendre beaucoup de cette réponse.
Shafik Yaghmour
9
Vous monsieur, devriez écrire un livre sur C.
Dillon Burton
1
Quelle belle réponse à une bonne question! Bravo @verbose!
benka
7
@verbose vous monsieur, avez été à la hauteur de votre nom .. :)
sleeping_dragon
44

Supposons que ptrpointe vers le i-ème élément du tableau arr.

  1. *ptr++évalue arr[i]et définit ptrpour pointer vers le (i + 1) -ème élément de arr. C'est équivalent à *(ptr++).

  2. *++ptrdéfinit ptrpour pointer vers le (i + 1) -ème élément de arret s'évalue vers arr[i+1]. C'est équivalent à *(++ptr).

  3. ++*ptraugmente arr[i]de un et évalue à sa valeur accrue; le pointeur ptrn'est pas touché. C'est équivalent à ++(*ptr).

Il y en a aussi un autre, mais vous aurez besoin de parenthèses pour l'écrire:

  1. (*ptr)++augmente arr[i]de un et s'évalue à sa valeur avant d'être augmentée; le pointeur ptrest à nouveau laissé intact.

Le reste, vous pouvez le découvrir vous-même; il a également été répondu par @Jaguar.

Nickie
la source
13

*ptr++ : post increment a pointer ptr

*++ptr : Pre Increment a pointer ptr

++*ptr : preincrement the value at ptr location

Lisez ici les opérateurs de pré-incrémentation et de post-incrémentation


Cela donnera Hellocomme sortie

int main()
{
    const char *p = "Hello";
    while(*p)
         printf("%c",*p++);//Increment the pointer here 
    return 0;
}
Jainendra
la source
@ Nik-Lz Oui, la sortie seraitHello
Jainendra
7

La condition dans votre boucle est mauvaise:

while(*p++)
    printf("%c",*p);

Est le même que

while(*p)
{
    p++;
    printf("%c",*p);
}

Et c'est faux, cela devrait être:

while(*p)
{
    printf("%c",*p);
    p++;
} 

*ptr++est le même que *(ptr++), qui est:

const char  *ptr = "example";
char  value;

value = *ptr;
++ptr;
printf("%c", value); // will print 'e'

*++ptrest le même que *(++ptr), qui est:

const char  *ptr = "example";
char  value;

++ptr;
value = *ptr;
printf("%c", value); // will print 'x'

++*ptrest le même que ++(*ptr), qui est:

const char  *ptr = "example";
char  value;

value = *ptr;
++value;
printf("%c", value); // will print 'f' ('e' + 1)
Nouney
la source
Je suis tout à fait d'accord avec la première partie de la réponse. Dans la deuxième partie, l'initialisation des pointeurs (vers des entiers!) Avec des entiers est déroutante pour quelqu'un qui a du mal à comprendre l'utilisation des pointeurs.
nickie
4

Vous avez raison sur la priorité, notez que le *a la priorité sur l'incrément de préfixe, mais pas sur l'incrément de suffixe. Voici comment ces ventilations:

*ptr++ - en allant de gauche à droite, déréférencer le pointeur, puis incrémenter la valeur du pointeur (pas ce à quoi il pointe, en raison de la priorité de postfix sur le déréférencement)

*++ptr - incrémenter le pointeur puis le déréférencer, car le préfixe et le déréférencement ont la même priorité et sont donc évalués dans l'ordre de droite à gauche

++*ptr- similaire à ce qui précède en termes de priorité, en allant à nouveau de droite à gauche pour déréférencer le pointeur, puis incrémenter ce sur quoi le pointeur pointe. Veuillez noter que dans votre cas, celui-ci entraînera un comportement non défini car vous essayez de modifier une variable en lecture seule ( char* p = "Hello";).

Nobilis
la source
3

Je vais ajouter mon point de vue parce que si les autres réponses sont correctes, je pense qu'il leur manque quelque chose.

 v = *ptr++

veux dire

 temp = ptr;
 ptr  = ptr + 1
 v    = *temp;

Tandis que

 v = *++ptr

veux dire

 ptr = ptr + 1
 v   = *ptr

Il est important de comprendre que post incrémentation (et post décrémentation) signifie

 temp = ptr       // Temp created here!!!
 ptr  = ptr + 1   // or - 1 if decrement)
 v    = *temp     // Temp destroyed here!!!

Pourquoi est-ce important? Eh bien en C ce n'est pas si important. En C ++, cela ptrpeut cependant être un type complexe comme un itérateur. Par exemple

 for (std::set<int>::iterator it = someSet.begin(); it != someSet.end(); it++)

Dans ce cas, parce que itc'est un type complexe it++peut-être avoir des effets secondaires en raison de la tempcréation. Bien sûr, si vous avez de la chance, le compilateur essaiera de jeter du code qui n'est pas nécessaire, mais si le constructeur ou le destructeur de l'itérateur fait quelque chose, il it++affichera ces effets lors de sa création temp.

Le court de ce que j'essaie de dire est Écrivez ce que vous voulez dire . Si vous voulez dire incrémenter ptr, n'écrivez ++ptrpas ptr++. Si tu veux dire temp = ptr, ptr += 1, tempalors écrisptr++

gman
la source
0
*ptr++    // 1

C'est la même chose que:

    tmp = *ptr;
    ptr++;

Ainsi, la valeur de l'objet pointé par ptrest récupérée, puis ptrincrémentée.

*++ptr    // 2

C'est la même chose que:

    ++ptr;
    tmp = *ptr;

Ainsi, le pointeur ptrest incrémenté, puis l'objet pointé par ptrest lu.

++*ptr    // 3

C'est la même chose que:

    ++(*ptr);

Ainsi, l'objet pointé par ptrest incrémenté; ptrlui-même est inchangé.

David R Tribble
la source
0

postfix et prefix ont une priorité plus élevée que la déréférence, donc

* ptr ++ ici post incrémentation ptr puis pointant vers la nouvelle valeur de ptr

* ++ ptr ici Pre Increment fist puis pointant vers la nouvelle valeur de ptr

++ * ptr ici obtient d'abord la valeur de ptr pointant vers et incrémente cette valeur

Kiran Padwal
la source
1
Ceci est une erreur. Postfix a une priorité plus élevée, mais le préfixe a la même priorité que la déréférence.
verbeux le
0

Expressions de pointeur: * ptr ++, * ++ ptr et ++ * ptr:

Remarque : les pointeurs doivent être initialisés et avoir une adresse valide. Parce que dans la RAM en dehors de notre programme (a.out), il y a beaucoup plus de programmes en cours d'exécution simultanément, c'est-à-dire que si vous essayez d'accéder à une mémoire qui n'était pas réservée à votre système d'exploitation, cela se produira par erreur de segmentation.

Avant d'expliquer cela, considérons un exemple simple?

#include<stdio.h>
int main()
{
        int num = 300;
        int *ptr;//uninitialized pointer.. must be initialized
        ptr = &num;
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
        *ptr = *ptr + 1;//*ptr means value/data on the address.. so here value gets incremented
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
        /** observe here that "num" got changed but manually we didn't change, it got modified by pointer **/
        ptr = ptr + 1;//ptr means address.. so here address got incremented
        /**     char pointer gets incremented by 1 bytes
          Integer pointer gets incremented by 4 bytes
         **/
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
}

analyser la sortie du code ci-dessus, j'espère que vous avez obtenu la sortie du code ci-dessus. Une chose est claire à partir du code ci-dessus est que le nom du pointeur ( ptr ) signifie que nous parlons d' adresse et que * ptr signifie que nous parlons d'abbout valeur / données.

CAS 1 : * ptr ++, * ++ ptr, * (ptr ++) et * (++ ptr):

Les 4 syntaxes mentionnées ci-dessus sont similaires, address gets incrementedmais la façon dont l'adresse est incrémentée est différente.

Remarque : pour résoudre une expression, découvrez combien d'opérateurs il y a dans l'expression, puis déterminez les priorités de l'opérateur. I plusieurs opérateurs ayant la même priorité vérifient alors l'ordre d'évolution ou d' associativité qui peut de droite (R) à gauche (L) ou de gauche à droite.

* ptr ++ : Ici 2 opérateurs sont là à savoir la de-reference (*) et ++ (increment). Les deux ont la même priorité, puis vérifiez l'associativité qui est de R à L.Commence donc à résoudre de droite à gauche, quels que soient les opérateurs qui viennent en premier.

* ptr ++ : first ++ est venu lors de la résolution de R à L, donc l'adresse est incrémentée mais son post-incrémentation.

* ++ ptr : Identique au premier ici aussi l'adresse est incrémentée mais son pré-incrémentation.

* (ptr ++) : Ici, il y a 3 opérateurs, parmi eux grouping () ayant la priorité la plus élevée, donc d'abord ptr ++ résolu c'est-à-dire que l'adresse est incrémentée mais postée.

* (++ ptr) : Identique au cas ci-dessus, ici aussi l'adresse est incrémentée mais pré-incrémentée.

CAS 2 : ++ * ptr, ++ (* ptr), (* ptr) ++:

mentionné ci-dessus, les 4 syntaxes sont similaires, en toutes les valeurs / données sont incrémentées, mais la façon dont la valeur est modifiée est différente.

++ * ptr : first * est venu lors de la résolution de R à L, donc la valeur est modifiée mais son pré-incrémentation.

++ (* ptr) : Identique au cas ci-dessus, la valeur est modifiée.

(* ptr) ++ : Ici, il y a 3 opérateurs, parmi eux grouping () ayant la priorité la plus élevée, Inside () * ptr est là, donc le premier * ptr est résolu c'est-à-dire que la valeur est incrémentée mais postée.

Remarque : ++ * ptr et * ptr = * ptr + 1 sont tous les deux identiques, dans les deux cas, la valeur est modifiée. ++ * ptr: une seule instruction (INC) est utilisée, la valeur est directement modifiée en un seul coup. * ptr = * ptr + 1: ici la première valeur est incrémentée (INC) puis assignée (MOV).

Pour comprendre tout ce qui précède, la syntaxe d'incrémentation sur le pointeur, considérons un code simple:

#include<stdio.h>
int main()
{
        int num = 300;
        int *ptr;
        ptr = &num;
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
        *ptr++;//address changed(post increment), value remains un-changed
//      *++ptr;//address changed(post increment), value remains un-changed
//      *(ptr)++;//address changed(post increment), value remains un-changed
//      *(++ptr);//address changed(post increment), value remains un-changed

//      ++*ptr;//value changed(pre increment), address remains un-changed
//      (*ptr)++;//value changed(pre increment), address remains un-changed
//      ++(*ptr);//value changed(post increment), address remains un-changed

        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
}

Dans le code ci-dessus, essayez de commenter / dé-commenter les commentaires et d'analyser les sorties.

Les pointeurs comme constants : il n'y a pas de moyens par lesquels vous pouvez rendre les pointeurs aussi constants, peu que je mentionne ici.

1) const int * p OR int const * p : Ici valueest constante , l' adresse n'est pas constante c'est- à- dire où p pointe? Une adresse? Sur cette adresse quelle est la valeur? Une certaine valeur, non? Cette valeur est constante, vous ne pouvez pas modifier cette valeur mais où pointe le pointeur? Une adresse non? Il peut également pointer vers une autre adresse.

Pour comprendre cela, considérons le code ci-dessous:

#include<stdio.h>
int main()
{
        int num = 300;
        const int *ptr;//constant value, address is modifible
        ptr = &num;
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
        *ptr++;//
//      *++ptr;//possible bcz you are trying to change address which is possible
//      *(ptr)++;//possible
//      *(++ptr);//possible

//      ++*ptr;//not possible bcz you trying to change value which is not allowed
//      (*ptr)++;//not possible
//      ++(*ptr);//not possible

        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
}

Essayez d'analyser la sortie du code ci-dessus

2) int const * p : il s'appelle ' **constant pointe**r' ieaddress is constant but value is not constant . Ici, vous n'êtes pas autorisé à modifier l'adresse mais vous pouvez modifier la valeur.

Remarque : le pointeur constant (cas ci-dessus) doit s'initialiser lorsqu'il est déclarié.

Pour comprendre cela, vérifions un code simple.

#include<stdio.h>
int main()
{
        int x = 300;
        int* const p;
        p = &x;
        printf("x = %d p =%p and *p = %d\n",num,p,*p);
}

Dans le code ci-dessus, si vous observez qu'il n'y a pas ++ * p ou * p ++ Vous pouvez penser que c'est un cas simple car nous ne changeons pas d'adresse ou de valeur mais cela produira une erreur. Pourquoi ? Raison que je mentionne dans les commentaires.

#include<stdio.h>
int main()
{
        int x = 300;
        /** constant pointer must initialize while decaring itself **/
        int* const p;//constant pointer i.e its pointing to some address(here its pointing to garbage), it should point to same address(i.e garbage ad
dress only 
        p = &x;// but here what we are doing ? we are changing address. we are making p to point to address of x instead of garbage address.
        printf("x = %d p =%p and *p = %d\n",num,p,*p);
}

Alors, quelle est la solution de ce problème?

     int* const p = &x;

pour en savoir plus sur ce cas, considérons l'exemple ci-dessous.

#include<stdio.h>
int main()
{
        int num = 300;
        int *const ptr = &num;//constant value, address is modifible
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
        *ptr++;//not possible
//      *++ptr;//not possible bcz you are trying to change address which is not possible
//      *(ptr)++;//not possible
//      *(++ptr);//not possible

//      ++*ptr;// possible bcz you trying to change value which is allowed
//      (*ptr)++;// possible
//      ++(*ptr);// possible
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
}

3) const int * const p : ici l'adresse et la valeur sont constantes .

Pour comprendre cela, vérifions le code ci-dessous

#include<stdio.h>
int main()
{
        int num = 300;
        const int* const ptr = &num;//constant value,constant address 
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
        *ptr++;//not possible
        ++*ptr;//not possible
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
}
Achal
la source
-1
const char *p = "Hello";   

*p means "Hello"
          ^
          | 
          p

*p++ means "Hello"
             ^
             | 
             p

*++p means "Hello"
            ^
            |     (WHILE THE STATEMENT IS EXECUTED)
            p

*++p means "Hello"
             ^
             |     (AFTER THE STATEMENT IS EXECUTED)
             p

++*psignifie que vous essayez d'incrémenter la valeur ASCII *pdont

   is "Hello"
       ^
       | 
       p

vous ne pouvez pas incrémenter la valeur car c'est une constante, vous obtiendrez donc une erreur

quant à votre boucle while, la boucle s'exécute jusqu'à ce qu'elle *p++atteigne la fin de la chaîne où il y a un caractère '\0'(NULL).

Maintenant que vous *p++ignorez le premier caractère, vous n'obtiendrez votre sortie qu'à partir du deuxième caractère.

Le code suivant ne produira rien car la boucle while a '\0'

const char *p = "Hello";
    while('\0') 
         printf("%c",*p);

Le code suivant vous donnera la même sortie que le code suivant, c'est-à-dire ello.

const char *p = "Hello";
    while(*++p)
         printf("%c",*p);

...................................

const char *p = "Hello";
    while(*p++)
         printf("%c",*p);
iammosespaulr
la source